int main(int argc, char const *argv[]) { char input[15][30]; int argnum, i; pid_list.head=NULL; pid_list.tail=NULL; enqueue(getppid(),"NEW SHELL",&pid_list); signal(SIGCHLD,childdead); signal(SIGTSTP,susp); signal(SIGQUIT,cont); setpriority(PRIO_PROCESS,0,-20); ver(); while (run){ printf("=>"); for (argnum=0; (scanf("%s",&input[argnum]))==1;argnum++) if (getchar()=='\n') break; if (strcmp(input[0],"ver")==0 && argnum==0) ver(); else if (strcmp(input[0],"help")==0 && argnum==0) help(); else if (strcmp(input[0],"help")==0 && argnum==1) helpcmd(input[argnum]); else if (strcmp(input[0],"ps")==0 && argnum==0) ps(); else if (strcmp(input[0],"kill")==0 && argnum==1) mykill(atoi(input[1])); else if (strcmp(input[0],"exec")==0 && argnum!=0) for (i=1; i<=argnum; i++) exec(input[i]); else if (strcmp(input[0],"exit")==0 && argnum==0) myexit(); else printf("Nosuch command. Check help for help.\n"); } }
/** * The main function for the command line mode. Parses switches and runs decompile(filename). * * \return Zero on success, nonzero on faillure. */ int Boomerang::commandLine(int argc, const char **argv) { printf("Boomerang %s\n", VERSION); // Display a version and date (mainly for release versions) if (argc < 2) usage(); progPath = argv[0]; size_t j = progPath.rfind('/'); // Chop off after the last slash if (j == (size_t)-1) j = progPath.rfind('\\'); // .. or reverse slash if (j != (size_t)-1) { // Do the chop; keep the trailing slash or reverse slash progPath = progPath.substr(0, j+1); } else { progPath = "./"; // Just assume the current directory } #ifdef _MSC_VER // For the console mode version; Windows GUI will override in windows.cpp // As a special case for MSVC testing, make the program path the parent of the dir with the .exe j = progPath.find("ebug\\", progPath.length() - (4+1)); if (j != std::string::npos) j--; // Point to the 'd' or 'D' if (j == std::string::npos) { j = progPath.rfind("elease\\", progPath.length() - (6+1)); if (j != std::string::npos) j--; // Point to the 'r' or 'R' } if (j != std::string::npos) progPath = progPath.substr(0, j); // Chop off "Release\" or "Debug\" SetCurrentDirectoryA(progPath.c_str()); // Note: setcwd() doesn't seem to work #endif outputPath = progPath + "output/"; // Default output path (can be overridden with -o below) // Parse switches on command line if ((argc == 2) && (strcmp(argv[1], "-h") == 0)) { help(); return 1; } if (argc == 3 && !strcmp(argv[1], "-h") && !strcmp(argv[2], "cmd")) { helpcmd(); return 1; } int kmd = 0; for (int i=1; i < argc; i++) { if (argv[i][0] != '-' && i == argc - 1) break; if (argv[i][0] != '-') usage(); switch (argv[i][1]) { case '-': break; // No effect: ignored case 'h': help(); break; case 'v': vFlag = true; break; case 'x': dumpXML = true; break; case 'X': experimental = true; std::cout << "Warning: experimental code active!\n"; break; case 'r': printRtl = true; break; case 't': traceDecoder = true; break; case 'T': if (argv[i][2] == 'c') { conTypeAnalysis = true; // -Tc: use old constraint-based type analysis dfaTypeAnalysis = false; } else if (argv[i][2] == 'd') dfaTypeAnalysis = true; // -Td: use data-flow-based type analysis (now default) break; case 'g': if(argv[i][2]=='d') dotFile = argv[++i]; else if(argv[i][2]=='c') generateCallGraph=true; else if(argv[i][2]=='s') { generateSymbols=true; stopBeforeDecompile=true; } break; case 'o': { outputPath = argv[++i]; char lastCh = outputPath[outputPath.size()-1]; if (lastCh != '/' && lastCh != '\\') outputPath += '/'; // Maintain the convention of a trailing slash break; } case 'p': if (argv[i][2] == 'a') { propOnlyToAll = true; std::cerr << " * * Warning! -pa is not implemented yet!\n"; } else { if (++i == argc) { usage(); return 1; } sscanf(argv[i], "%i", &numToPropagate); } break; case 'n': switch(argv[i][2]) { case 'b': noBranchSimplify = true; break; case 'c': noDecodeChildren = true; break; case 'd': noDataflow = true; break; case 'D': noDecompile = true; break; case 'l': noLocals = true; break; case 'n': noRemoveNull = true; break; case 'P': noPromote = true; break; case 'p': noParameterNames = true; break; case 'r': noRemoveLabels = true; break; case 'R': noRemoveReturns = true; break; case 'g': noGlobals = true; break; case 'G': #ifndef NO_GARBAGE_COLLECTOR GC_disable(); #endif break; default: help(); } break; case 'E': noDecodeChildren = true; // Fall through case 'e': { ADDRESS addr; int n; decodeMain = false; if (++i == argc) { usage(); return 1; } if (argv[i][0] == '0' && argv[i+1][1] == 'x') { n = sscanf(argv[i], "0x%x", &addr); } else { n = sscanf(argv[i], "%i", &addr); } if (n != 1) { std::cerr << "bad address: " << argv[i] << std::endl; exit(1); } entrypoints.push_back(addr); } break; case 's': { if (argv[i][2] == 'f') { symbolFiles.push_back(argv[i+1]); i++; break; } ADDRESS addr; int n; if (++i == argc) { usage(); return 1; } if (argv[i][0] == '0' && argv[i+1][1] == 'x') { n = sscanf(argv[i], "0x%x", &addr); } else { n = sscanf(argv[i], "%i", &addr); } if (n != 1) { std::cerr << "bad address: " << argv[i+1] << std::endl; exit(1); } const char *nam = argv[++i]; symbols[addr] = nam; } break; case 'd': switch(argv[i][2]) { case 'a': printAST = true; break; case 'c': debugSwitch = true; break; case 'd': debugDecoder = true; break; case 'g': debugGen = true; break; case 'l': debugLiveness = true; break; case 'p': debugProof = true; break; case 's': stopAtDebugPoints = true; break; case 't': // debug type analysis debugTA = true; break; case 'u': // debug unused locations (including returns and parameters now) debugUnused = true; break; default: help(); } break; case 'm': if (++i == argc) { usage(); return 1; } sscanf(argv[i], "%i", &maxMemDepth); break; case 'i': if (argv[i][2] == 'c') decodeThruIndCall = true; // -ic; if (argv[i][2] == 'w') // -iw if (ofsIndCallReport) { std::string fname = getOutputPath() + "indirect.txt"; ofsIndCallReport = new std::ofstream(fname.c_str()); } break; case 'L': if (argv[i][2] == 'D') #if USE_XML loadBeforeDecompile = true; #else std::cerr << "LD command not enabled since compiled without USE_XML\n"; #endif break; case 'S': if (argv[i][2] == 'D') #if USE_XML saveBeforeDecompile = true; #else std::cerr << "SD command not enabled since compiled without USE_XML\n"; #endif else { sscanf(argv[++i], "%i", &minsToStopAfter); } break; case 'k': kmd = 1; break; case 'P': progPath = argv[++i]; if (progPath[progPath.length()-1] != '\\') progPath += "\\"; break; case 'a': assumeABI = true; break; case 'l': if (++i == argc) { usage(); return 1; } sscanf(argv[i], "%i", &propMaxDepth); break; default: help(); } }
/** * Parse and execute a command supplied in interactive mode. * * \param argc The number of arguments. * \param argv Pointers to the arguments. * * \return A value indicating what happened. * * \retval 0 Success * \retval 1 Faillure * \retval 2 The user exited with \a quit or \a exit */ int Boomerang::parseCmd(int argc, const char **argv) { static Prog *prog = NULL; if (!strcmp(argv[0], "decode")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } const char *fname = argv[1]; Prog *p = loadAndDecode(fname); if (p == NULL) { std::cerr << "failed to load " << fname << "\n"; return 1; } prog = p; #if USE_XML } else if (!strcmp(argv[0], "load")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } const char *fname = argv[1]; XMLProgParser *p = new XMLProgParser(); Prog *pr = p->parse(fname); if (pr == NULL) { // try guessing pr = p->parse((outputPath + fname + "/" + fname + ".xml").c_str()); if (pr == NULL) { std::cerr << "failed to read xml " << fname << "\n"; return 1; } } prog = pr; } else if (!strcmp(argv[0], "save")) { if (prog == NULL) { std::cerr << "need to load or decode before save!\n"; return 1; } XMLProgParser *p = new XMLProgParser(); p->persistToXML(prog); #endif } else if (!strcmp(argv[0], "decompile")) { if (argc > 1) { Proc *proc = prog->findProc(argv[1]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[1] << "\n"; return 1; } if (proc->isLib()) { std::cerr << "cannot decompile a lib proc\n"; return 1; } int indent = 0; ((UserProc*)proc)->decompile(new ProcList, indent); } else { prog->decompile(); } } else if (!strcmp(argv[0], "codegen")) { if (argc > 1 ) { Cluster *cluster = prog->findCluster(argv[1]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[1] << "\n"; return 1; } prog->generateCode(cluster); } else { prog->generateCode(); } } else if (!strcmp(argv[0], "move")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "proc")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } Cluster *cluster = prog->findCluster(argv[3]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } proc->setCluster(cluster); } else if (!strcmp(argv[1], "cluster")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } Cluster *parent = prog->findCluster(argv[3]); if (parent == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } parent->addChild(cluster); } else { std::cerr << "don't know how to move a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "add")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = new Cluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot create cluster " << argv[2] << "\n"; return 1; } Cluster *parent = prog->getRootCluster(); if (argc > 3) { parent = prog->findCluster(argv[3]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } } parent->addChild(cluster); } else { std::cerr << "don't know how to add a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "delete")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } if (cluster->hasChildren() || cluster == prog->getRootCluster()) { std::cerr << "cluster " << argv[2] << " is not empty\n"; return 1; } if (prog->clusterUsed(cluster)) { std::cerr << "cluster " << argv[2] << " is not empty\n"; return 1; } unlink(cluster->getOutPath("xml")); unlink(cluster->getOutPath("c")); assert(cluster->getParent()); cluster->getParent()->removeChild(cluster); } else { std::cerr << "don't know how to delete a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "rename")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "proc")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } Proc *nproc = prog->findProc(argv[3]); if (nproc != NULL) { std::cerr << "proc " << argv[3] << " already exists\n"; return 1; } proc->setName(argv[3]); } else if (!strcmp(argv[1], "cluster")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } Cluster *ncluster = prog->findCluster(argv[3]); if (ncluster == NULL) { std::cerr << "cluster " << argv[3] << " already exists\n"; return 1; } cluster->setName(argv[3]); } else { std::cerr << "don't know how to rename a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "info")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "prog")) { std::cout << "prog " << prog->getName() << ":\n"; std::cout << "\tclusters:\n"; prog->getRootCluster()->printTree(std::cout); std::cout << "\n\tlibprocs:\n"; PROGMAP::const_iterator it; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (p->isLib()) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n\tuserprocs:\n"; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (!p->isLib()) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n"; return 0; } else if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } std::cout << "cluster " << cluster->getName() << ":\n"; if (cluster->getParent()) std::cout << "\tparent = " << cluster->getParent()->getName() << "\n"; else std::cout << "\troot cluster.\n"; std::cout << "\tprocs:\n"; PROGMAP::const_iterator it; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (p->getCluster() == cluster) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n"; return 0; } else if (!strcmp(argv[1], "proc")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } std::cout << "proc " << proc->getName() << ":\n"; std::cout << "\tbelongs to cluster " << proc->getCluster()->getName() << "\n"; std::cout << "\tnative address " << std::hex << proc->getNativeAddress() << std::dec << "\n"; if (proc->isLib()) std::cout << "\tis a library proc.\n"; else { std::cout << "\tis a user proc.\n"; UserProc *p = (UserProc*)proc; if (p->isDecoded()) std::cout << "\thas been decoded.\n"; //if (p->isAnalysed()) // std::cout << "\thas been analysed.\n"; } std::cout << "\n"; return 0; } else { std::cerr << "don't know how to print info about a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "print")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[1]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[1] << "\n"; return 1; } if (proc->isLib()) { std::cerr << "cannot print a libproc.\n"; return 1; } ((UserProc*)proc)->print(std::cout); std::cout << "\n"; return 0; } else if (!strcmp(argv[0], "exit")) { return 2; } else if (!strcmp(argv[0], "quit")) { return 2; } else if (!strcmp(argv[0], "help")) { helpcmd(); return 0; } else { std::cerr << "unknown cmd " << argv[0] << ".\n"; return 1; } return 0; }