fxos/fxos/main.cpp

158 lines
4.0 KiB
C++

#include "fxos-cli.h"
#include <fxos/load.h>
#include <fxos/errors.h>
#include <getopt.h>
using namespace FxOS;
static char const *help_string = R"(
usage: fxos info <os file>
fxos disasm <os file> (-a <address> | -s <syscall id>) [options...]
fxos disasm -b <binary file> [options...]
fxos analyze [-f] [-s] [-a] [-r] <number> <os file> [options...]
fxos is a reverse-engineering tool to disassemble and analyze fx9860g-like
OS dumps, providing efficient annotations through an editable database.
Commands:
info Identify an OS image: version, platform, date, checksums...
disasm Disassemble and annotate code with relative address targets,
syscall invocations, control flow, constant propagation and hints
about memory structure.
analyze Dig an address or syscall number, finding syscall references,
4-aligned occurrences, memory region and probable role.
General options:
-b Work with an arbitrary binary file, not an OS
-3, --sh3 Assume SH3 OS and platform (default: SH4)
-4, --sh4 Assume SH4 OS and platform (default: SH4)
Database extensions:
--load <file> Read documentation from <file>
--load <folder> Read documentation recursively from <folder>
Disassembly options:
-a <address> Start disassembling at this address
-s <syscall id> Start disassembling at this syscall's address
-l <length> Length of region
--passes=<list> Execute the specified comma-separated list of passes
The default list of passes is pcrel,cfg,cstprop,syscall,regs. The available
passes are the following:
pcrel Resolve PC-relative references as their target address
cfg Build the control flow graph (uses pcrel)
cstprop Propagate constants by abstract interpretation (uses cfg)
syscall Annotate code with reverse syscalls
regs Annotate code with peripheral register addresses
Analysis modes:
-f, --full Run all analysis passes on <number> (same as -sar)
-s, --syscall Run syscall ID analysis
-a, --address Run code/data address analyis
-r, --register Run peripheral register analysis
Analysis options:
--occurrences <num> Show at most <num> occurrences (integer or "all")
All numbers support base prefixes "0" (octal) and "0x" (hexadecimal).
)"+1;
int main_info(int argc, char **argv)
{
int error=0, option=0, mpu=0;
struct option const longs[] = {
{ "help", no_argument, NULL, 'h' },
{ "sh3", no_argument, NULL, '3' },
{ "sh4", no_argument, NULL, '4' },
};
while(option >= 0 && option != '?')
switch((option = getopt_long(argc, argv, "h34", longs, NULL)))
{
case 'h':
std::cerr << help_string;
break;
case '3':
case '4':
/* TODO: Use sh3/sh4 information in [fxos info)? */
mpu = option;
break;
case '?':
error = 1;
}
if(error) return 1;
char const *path = argv[optind + 1];
if(!path)
{
std::cerr << help_string;
return 1;
}
try {
os_info(path);
}
catch(std::exception &e) {
std::cerr << "error: " << e.what() << "\n";
return 1;
}
return 0;
}
int main_disassembly(int argc, char **argv)
{
std::cerr << "doing main_disasm, which is incomplete x_x\n";
try
{
FxOS::load("data/sh3.txt");
FxOS::load("data/sh4.txt");
}
catch(FxOS::SyntaxError &e)
{
std::cerr << e.file() << ":" << e.line() << ": " <<
e.what() << "\n" << std::flush;
return 1;
}
return 0;
}
int main_analyze(int argc, char **argv)
{
std::cerr << "doing main_analyze, which is incomplete x_x\n";
return 0;
}
int main(int argc, char **argv)
{
if(argc < 2)
{
std::cerr << help_string;
return 1;
}
std::string cmd = argv[1];
argv[1] = (char *)"";
if(cmd == "info")
return main_info(argc, argv);
else if(cmd == "disasm")
return main_disassembly(argc, argv);
else if(cmd == "analyze")
return main_analyze(argc, argv);
else if(cmd == "-?" || cmd == "-h" || cmd == "--help")
{
std::cerr << help_string;
return 0;
}
std::cerr << "invalid operation '" << cmd << "'\n";
std::cerr << "Try '" << argv[0] << " --help'.\n";
return 1;
}