fxos/shell/d.cpp

127 lines
3.2 KiB
C++

#include "commands.h"
#include "errors.h"
#include "parser.h"
#include "shell.h"
#include <fmt/core.h>
#include <fxos/disassembly.h>
#include <fxos/passes/pcrel.h>
#include <fxos/passes/syscall.h>
#include <fxos/view/assembly.h>
#include <fxos/function.h>
#include <fxos/analysis.h>
#include <fxos/util/Timer.h>
#include <fxos/util/log.h>
//---
// d
//---
struct _d_args
{
std::variant<long, Range> location;
bool analyze = false;
};
static _d_args parse_d(Session &session, Parser &parser)
{
_d_args args;
if(!session.currentBinary())
return {};
parser.option("-a", [&args](Parser &) { args.analyze = true; });
parser.accept_options();
args.location = parser.expr_or_range(session.currentBinary());
parser.end();
return args;
}
void _d(Session &session, std::variant<long, Range> location, bool analyze)
{
Binary *b = session.currentBinary();
if(!b)
return FxOS_log(ERR, "No current binary!\n");
if(std::holds_alternative<Range>(location)) {
Range range = std::get<Range>(location);
if(range.start & 1) {
fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n",
range.start, range.start + 1);
range.start++;
}
if(range.end & 1) {
fmt::print("address 0x{:08x} is odd, ending at 0x{:08x}\n",
range.end, range.end - 1);
range.end--;
}
if(range.start >= range.end)
return;
/* Load the block into memory */
for(uint32_t pc = range.start; pc < range.end; pc += 2)
b->vspace().disasm.getInstructionAt(pc, true);
PcrelPass p(*b);
p.analyzeAllInstructions();
OS *os = b->OSAnalysis();
if(os) {
SyscallPass p(*b, os);
p.analyzeAllInstructions();
}
MemoryRegion r;
r.start = range.start;
r.end = range.end - 1;
viewAssemblyLegacyRegion(*b, r);
}
else {
uint32_t address = std::get<long>(location);
if(address & 1) {
fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n",
address, address + 1);
address++;
}
Function f(*b, address);
if(f.exploreFunctionAt(address)) {
if(analyze)
f.runAnalysis();
ViewAssemblyOptions opts;
opts.binary = b;
opts.printFunctionAnalysis = analyze;
opts.showInstructionDetails = !analyze;
viewAssemblyFunction(f, &opts);
}
}
}
//---
// Command registration
//---
static ShellCommand _d_cmd(
"d",
[](Session &s, Parser &p) {
auto args = parse_d(s, p);
_d(s, args.location, args.analyze);
},
[](Session &s, Parser &p) { parse_d(s, p); }, "Disassemble", R"(
d [-a] <address>
d <range>
Disassembles code. In the first form, explores a function at the provided
address (without modifying the binary), exploring branches until function
terminators, invalid instructions or dynamically-computed jumps. If -a is
specified, also perform static analysis.
In the second form, disassembles instructions in the specified range. (This is
an older feature with less support for advanced features.)
)");