/* Decompile.java (c) 2008-2013 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.tools; import ejs.base.logging.LoggingUtils; import ejs.base.utils.HexUtils; import ejs.base.utils.Pair; import gnu.getopt.Getopt; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; import v9t9.common.asm.IDecompilePhase; import v9t9.common.machine.IMachine; import v9t9.common.memory.IMemoryDomain; import v9t9.tools.asm.decomp.Decompiler; import v9t9.tools.asm.decomp.Decompiler9900; import v9t9.tools.utils.Category; import v9t9.tools.utils.ToolUtils; @Category(Category.DEVELOPMENT) public class Decompile { private static final String PROGNAME = Decompile.class.getName(); private static void help(IMachine machine) { System.out .println("\n" + "V9t9 Decompiler v0.1\n" + "\n" + "Usage: " + PROGNAME + " [options] { -r from:to -d from:to }\n" + "\t{-m<domain> <address> <raw file>} {<FIAD memory image>}\n" + "\n" + PROGNAME + " will 'decompile' programs (higher-level than Disassemble)\n" + "\n" + "-m<domain> <address> <raw file>: load <raw file> into memory at <address>\n" + "Domains:"); for (IMemoryDomain domain : machine.getMemory().getDomains()) { System.out.println("\t" + domain.getIdentifier()); } System.out.println("\n" + "Remaining files are assumed to have a memory image header and load into RAM.\n" + "\n" + "Options:\n" + "\t\t-? -- this help\n" + "\t\t-o <file> -- send output to <file> (else stdout)\n" + "\t\t-r <addr>:<addr> -- specify range to disassemble\n" + "\t\t-d <addr>:<addr> -- specify range to treat as data\n" + "\t\t-s <addr> -- add new REF/DEF symbol table address (end of table)\n" + "\n"); } /** * @param args */ public static void main(String[] args) throws IOException { LoggingUtils.setupNullLogging(); Getopt getopt; IMachine machine = ToolUtils.createMachine(); Decompiler dc = new Decompiler9900(machine); List<Integer> refDefTables = new ArrayList<Integer>(); List<Pair<Integer, Integer>> ranges = new ArrayList<Pair<Integer,Integer>>(); boolean gotFile = false; getopt = new Getopt(PROGNAME, args, "?o:r:d:s:m:::"); String outfilename = null; int opt; while ((opt = getopt.getopt()) != -1) { switch (opt) { case '?': help(machine); break; case 'm': { String domainName = getopt.getOptarg(); int idx = getopt.getOptind(); if (domainName == null) { domainName = args[idx++]; } String addrStr = args[idx]; String fileName = args[idx+1]; getopt.setOptind(idx+2); try { ToolUtils.loadMemory(machine, domainName, fileName, addrStr, ranges); gotFile = true; } catch (IOException e) { if (e.getCause() != null) System.err.println(e.getMessage() + "\n" + e.getCause()); else System.err.println(e.getMessage()); System.exit(1); } break; } case 'o': outfilename = getopt.getOptarg(); break; case 'r': dc.addRangeFromArgv(getopt.getOptarg(), true /* code */); break; case 'd': dc.addRangeFromArgv(getopt.getOptarg(), false /* code */); break; case 's': { int addr = HexUtils.parseHexInt(getopt.getOptarg()); refDefTables.add(new Integer(addr)); break; } default: throw new AssertionError(); } } // leftover files are FIAD int idx = getopt.getOptind(); while (idx < args.length) { String name = args[idx++]; try { ToolUtils.loadMemoryImage(machine, name, ranges); } catch (IOException e) { System.err.println("failed to load file: " + e.getMessage()); System.exit(1); } gotFile = true; } if (!gotFile) { help(machine); System.err.println("no files specified"); System.exit(1); } if (dc.getHighLevel().getMemoryRanges().isEmpty()) { if (ranges.isEmpty()) { help(machine); System.err.println(PROGNAME + ": no code sections defined: use -r or -d options to delineate"); System.exit(1); } else { System.err.println(PROGNAME + ": assuming all memory is code; use -r or -d options to delineate code and data"); for (Pair<Integer, Integer> ent : ranges) { dc.addRange(ent.first, ent.second, true); } } } dc.getOptions().refDefTables = refDefTables; machine.getMemoryModel().loadMemory(machine.getEventNotifier()); IDecompilePhase phase = dc.decompile(); PrintStream os = outfilename != null ? new PrintStream(new File(outfilename)) : System.out; phase.dumpRoutines(os); if (outfilename != null) os.close(); } }