#include #include #include #include #include static const char *help_string = "usage: %1$s info ( | -b )\n" " %1$s disasm (-a
| -s ) [options...]\n" " %1$s disasm -b [options...]\n" " %1$s analyze [-f|-s|-a|-r] [options...]\n" "\n" "fxos disassembles or analyzes binary and OS files for efficient reverse-\n" "engineering. It currently only supports fx9860g binaries.\n" "\n" "Commands:\n" " info Identify an OS image: version, platform, date, checksums...\n" " Identify the architecture of a binary file.\n" " disasm Disassemble and annotate code with relative address targets,\n" " syscall invocations and hints about memory structure.\n" " analyze Dig an address or syscall number, finding syscall call graph,\n" " 4-aligned occurrences, memory region and probable role.\n" "\n" "General options:\n" " -b Disassemble any binary file, not an OS file\n" " -3, --sh3 Assume SH3 OS and platform (default: guess)\n" " -4, --sh4 Assume SH4 OS and platform (default: guess)\n" " --ram Read RAM dumps from \n" " --table-asm Read more instruction patterns in \n" " --table-call Read more syscall prototypes in \n" "\n" "Disassembly region options:\n" " -a
Start disassembling at this address\n" " -s Start disassembling at this syscall's address\n" " -l Length of region\n" "\n" "Analysis modes:\n" " -f, --full Find everything that can be known about \n" " -s, --syscall is a syscall ID\n" " -a, --address is a code/data address in ROM or RAM\n" " -r, --register is a register or peripheral address\n" "\n" "Analysis options:\n" " --occurrences Show at most occurrences (integer or \"all\")\n"; /* "Low-level" command-line option set */ struct options { const char *input; int target; const char *ram; const char *a; const char *s; size_t l; int f; int r; const char *occ; }; int main(int argc, char **argv) { int command = 0, error = 0; struct options opt = { 0 }; /* For string -> int conversions, first non-int character */ /* Get command name */ if(argc >= 2) { if(!strcmp(argv[1], "info")) command = 'i'; if(!strcmp(argv[1], "disasm")) command = 'd'; if(!strcmp(argv[1], "analyze")) command = 'a'; if(!command && argv[1][0] != '-') { fprintf(stderr, "invalid operation: '%s'\n", argv[1]); fprintf(stderr, "Try '%s --help'.\n", argv[0]); return 1; } if(command) argv[1] = ""; } enum { OPT_RAM = 1, OPT_ASM = 2, OPT_CALL = 3, OPT_OCC = 4, }; const struct option longs[] = { { "help", no_argument, NULL, 'h' }, { "sh3", no_argument, NULL, '3' }, { "sh4", no_argument, NULL, '4' }, { "ram", required_argument, NULL, OPT_RAM }, { "table-asm", required_argument, NULL, OPT_ASM }, { "table-call", required_argument, NULL, OPT_CALL }, { "full", no_argument, NULL, 'f' }, { "syscall", no_argument, NULL, 's' }, { "address", no_argument, NULL, 'a' }, { "register", no_argument, NULL, 'r' }, { "occurrences", required_argument, NULL, OPT_OCC }, }; int option = 0; while(option >= 0 && option != '?') switch((option = getopt_long(argc, argv, "hb34a::s::l:fr",longs,NULL))) { case 'h': fprintf(stderr, help_string, argv[0]); return 0; case '3': case '4': opt.target = option; break; case OPT_RAM: opt.ram = optarg; break; case OPT_ASM: tables_add_asm(optarg); break; case OPT_CALL: tables_add_syscall(optarg); break; case 'f': opt.f = 1; break; case 's': opt.s = optarg; break; case 'a': opt.a = optarg; break; case 'l': opt.l = integer(optarg, &error); break; case 'r': opt.r = 1; break; case OPT_OCC: opt.occ = optarg; break; case '?': error = 1; break; } if(error) return 1; opt.input = argv[optind]; if(!opt.input) { fprintf(stderr, help_string, argv[0]); return 1; } /* Load default tables (user-specified tables will override them) */ tables_add_asm (FXSDK_PREFIX "/share/assembly-sh3.txt"); tables_add_syscall(FXSDK_PREFIX "/share/syscalls.txt"); /* Change interpretation of arguments depending on mode */ printf("Operation is '%c'\n", command); printf(" input=%s\n", opt.input); printf(" target='%c'\n", opt.target); printf(" ram=%s\n", opt.ram); printf(" a=%s\n", opt.a); printf(" s=%s\n", opt.s); printf(" l=%zu\n", opt.l); printf(" f=%d\n", opt.f); printf(" r=%d\n", opt.r); printf(" occ=%s\n", opt.occ); /* TODO: Execution procedure: TODO: 1. Identify architecture TODO: 2. Load RAM data, syscall tables, peripheral modules, etc TODO: 3. Execute command */ return 0; }