/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.build; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import org.jnode.build.x86.BootImageBuilder; /** * @author Ewout Prangsma (epr@users.sourceforge.net) */ public class AddressFinder { private static final int HDRLEN = 15; private static final int MAXWIDTH = 75; private static final String NDISASM = System.getProperty("os.name").toLowerCase().contains("win") ? "ndisasmw" : "ndisasm"; private static final ArchInfo[] archs = { new ArchInfo("x86", "all/build/x86/32bits/bootimage/bootimage.bin", "all/build/x86/bootimage/32bits/bootimage.lst", NDISASM + " -u -o "), new ArchInfo("x86_64", "all/build/x86/64bits/bootimage/bootimage.bin", "all/build/x86/64bits/bootimage/bootimage.lst", "udis86 --code64 --offset --origin ")}; public static void main(String[] args) throws IllegalArgumentException, SecurityException, IOException, InterruptedException { long loadAddress = BootImageBuilder.LOAD_ADDR; long address; boolean disasm = false; int disasmLength = 128; if (args.length > 0) { final String archName = args[0]; final ArchInfo arch = findArch(archName); final String listFileName = arch.getListFile(); final String imageFileName = arch.getBootImageFile(); int i; for (i = 1; i < args.length; i++) { String arg = args[i]; if (arg.charAt(0) == '-') { arg = arg.substring(1); if (arg.equals("d")) { disasm = true; } else if (arg.equals("l")) { disasmLength = Integer.parseInt(args[++i]); } else { usage(); } } else { break; } } address = Long.parseLong(args[i], 16); final long labelAddress = findLabel(listFileName, address); if (disasm) { disasm(arch, imageFileName, labelAddress, disasmLength, loadAddress); } } else { usage(); } } private static ArchInfo findArch(String name) { for (int i = 0; i < archs.length; i++) { if (archs[i].getArch().equals(name)) { return archs[i]; } } usage(); return null; } private static void usage() { System.out.println("Usage: findaddress architecture [-d] [-l length] address"); System.exit(1); } private static long findLabel(String listFileName, long address) throws IOException { FileReader fin = new FileReader(listFileName); try { BufferedReader in = new BufferedReader(fin); String line; long lastAddress = -1; String lastLabel = null; while ((line = in.readLine()) != null) { if (line.startsWith("$")) { final int idx = line.indexOf('\t'); final long laddr = Long.parseLong(line.substring(1, idx), 16); if (laddr <= address) { lastAddress = laddr; lastLabel = line.substring(idx + 1); } else { break; } } } System.out.println("Found:"); println("Address:", "0x" + Long.toHexString(lastAddress)); printLabel(lastLabel); System.out.println(); return lastAddress; } finally { fin.close(); } } private static void printLabel(String label) { int idx; final String BCI = "__bci_"; String indent = ""; while ((idx = label.indexOf(BCI)) >= 0) { println(indent + "Label:", label.substring(0, idx)); label = label.substring(idx + BCI.length()); idx = 0; while ((idx < label.length()) && Character.isDigit(label.charAt(idx))) { idx++; } println(indent + "BCI:", label.substring(0, idx)); label = (idx < label.length()) ? label.substring(idx + 1) : ""; indent += " "; } } private static void println(String hdr, String arg) { String s = fixlen(hdr, HDRLEN) + arg; while (s.length() > 0) { if (s.length() <= MAXWIDTH) { System.out.println(s); s = ""; } else { System.out.println(s.substring(0, MAXWIDTH)); s = fixlen("", HDRLEN) + s.substring(MAXWIDTH); } } } private static String fixlen(String v, int length) { while (v.length() < length) { v += " "; } if (v.length() > length) { v = v.substring(0, length); } return v; } private static void disasm(ArchInfo arch, String imageFileName, long address, int length, long loadAddress) throws IllegalArgumentException, SecurityException, IOException, InterruptedException { final RandomAccessFile raf = new RandomAccessFile(imageFileName, "r"); try { final long offset = address - loadAddress; raf.seek(offset); final byte[] data = new byte[length]; raf.readFully(data); File tmpFile = File.createTempFile("jnode", "bin"); FileOutputStream os = new FileOutputStream(tmpFile); os.write(data); os.close(); final String cmdLine = arch.getDisasmCmd() + address + " " + tmpFile.getAbsolutePath(); exec(cmdLine); //tmpFile.delete(); } finally { raf.close(); } } private static void exec(String cmdLine) throws IOException, InterruptedException { Process proc = Runtime.getRuntime().exec(cmdLine); CopyThread stderr = new CopyThread(proc.getErrorStream(), System.out); CopyThread stdout = new CopyThread(proc.getInputStream(), System.out); stderr.start(); stdout.start(); proc.waitFor(); } private static final class ArchInfo { private final String arch; private final String listFile; private final String bootImageFile; private final String disasmCmd; /** * @param bootImageFile * @param listFile * @param disasmCmd */ public ArchInfo(String arch, String bootImageFile, final String listFile, final String disasmCmd) { this.arch = arch; this.bootImageFile = bootImageFile; this.listFile = listFile; this.disasmCmd = disasmCmd; } public final String getArch() { return arch; } public final String getBootImageFile() { return bootImageFile; } public final String getDisasmCmd() { return disasmCmd; } public final String getListFile() { return listFile; } } static class CopyThread extends Thread { private final InputStream is; private final OutputStream out; public CopyThread(InputStream is, OutputStream out) { this.is = is; this.out = out; } public void run() { int ch; try { while ((ch = is.read()) >= 0) { out.write(ch); } } catch (IOException e) { e.printStackTrace(); } } } }