fxos/shell/e.cpp

86 lines
2.2 KiB
C++

#include "shell.h"
#include "parser.h"
#include "commands.h"
#include "errors.h"
#include <fmt/core.h>
#include <optional>
#include <fxos/util/log.h>
//---
// e
//---
struct _e_args
{
std::string binary_name;
std::vector<long> values;
};
static _e_args parse_e(Session &session, Parser &parser)
{
_e_args args {};
parser.option("-b",
[&args](Parser &p) { args.binary_name = p.symbol("binary_name"); });
parser.accept_options();
Binary *binary = session.currentBinary();
if(!args.binary_name.empty()) {
binary = session.project().getBinary(args.binary_name);
if(!binary) {
std::string msg
= fmt::format("No binary “{}” in project", args.binary_name);
if(parser.completing())
throw Parser::CompletionRequest("_error", msg);
else
FxOS_log(ERR, "%s", msg.c_str());
}
}
while(!parser.at_end())
args.values.push_back(parser.expr(binary));
parser.end();
return args;
}
void _e(Session &, std::string, std::vector<long> const &values)
{
for(long value: values) {
long print_val = labs(value);
/* Hexa format */
int length = (print_val <= (1ll << 32) ? 8 : 16) + 2 + (value < 0);
std::string format = fmt::format("{{:#0{}x}}", length);
fmt::print(format, value);
if(print_val <= 100 || print_val % 100 <= 1 || print_val % 100 >= 99)
fmt::print(" = {}", print_val);
fmt::print("\n");
}
}
static ShellCommand _e_cmd(
"e",
[](Session &s, Parser &p) {
auto const &args = parse_e(s, p);
_e(s, args.binary_name, args.values);
},
[](Session &s, Parser &p) { parse_e(s, p); }, "Evaluate expression", R"(
e [-b <binary>] [<expression>...]
Evaluates the specified expressions. The expressions may include syscall
references (%0ab), named symbols (TRA), and arithmetic expressions (within
parentheses).
The resulting values undergo a simple analysis which recovers symbol names and
syscall addresses within the current binary (or the one specified with -b).
e TRA (Bdisp_PutDisp_DD+2)
Evaluate the address of the TRA register, and the address of the second
instruction of Bdisp_PutDisp_DD.
)");