158 lines
4.0 KiB
C++
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;
|
|
}
|