Compare commits

..

1 Commits

Author SHA1 Message Date
Lephenixnoir fb639962a5
shell: provide parser with expr_or_range() function 2022-12-08 22:51:34 +01:00
20 changed files with 136 additions and 446 deletions

View File

@ -108,10 +108,6 @@ struct Instruction
struct Function
{
/* Create a bare function with no detailed information */
Function(uint32_t pc);
/* Function's entry point */
uint32_t address;
/* List of subfunctions called. TODO: Not yet populated by anyone */
@ -148,9 +144,6 @@ struct Claim
/* Utility to check for intersections */
bool intersects(Claim const &other) const;
/* Check equality of claims (raw equality) */
bool operator==(Claim const &other) const;
/* String representation */
std::string str() const;
};
@ -192,8 +185,6 @@ struct Disassembly
bool hasFunctionAt(uint32_t pc);
/* Find a function by address; returns nullptr if not yet defined */
Function *getFunctionAt(uint32_t pc);
/* Find a function and create it empty if it's not yet defined */
Function *getOrCreateFunctionAt(uint32_t pc);
// Claim information
@ -203,20 +194,13 @@ struct Disassembly
/* Access the claim that owns the address, if there is one */
Claim const *getClaimAt(uint32_t address);
/* Find the first claim that overlaps this region, if any */
/* Access the first claim that overlaps this region, if any */
Claim const *findClaimConflict(uint32_t address, int size);
/* Find all (or up to max ≥ 0) claims that overlaps this region */
std::vector<Claim const *> findClaimConflicts(
uint32_t address, int size, int max = -1);
/* Add a new exclusive claim. If there is any intersection with previous
claims which do not compare equal to c, this fails. */
claims, this fails. */
bool addExclusiveClaim(Claim const &c);
/* Get all claims owned by a certain address. */
std::vector<Claim const *> findClaimsOwnedBy(uint32_t address);
// TODO: Add non-exclusive claims/handle collisions

View File

@ -175,8 +175,6 @@ struct AsmInstruction
bool isjump() const noexcept;
/* Check whether it's a conditional jump */
bool iscondjump() const noexcept;
/* Check whether instruction is a function call */
bool iscall() const noexcept;
/* Check whether instruction has a delay slot */
bool isdelayed() const noexcept;
/* Check whether instruction can be used in a delay slot */

View File

@ -32,6 +32,7 @@ namespace FxOS {
struct MemoryArea
{
public:
/* Userspace seen from user and privileged mode */
static MemoryArea U0, P0;
/* Second half of memory, only for privileged mode */
@ -97,7 +98,7 @@ struct MemoryRegion
/* Returns the size of the region */
uint32_t size() const noexcept;
/* Returns the area associated with the region (assuming it is fully
/* Returns the area associated to the region (assuming it is fully
contained in one, which should always be the case) */
MemoryArea area() const noexcept;

View File

@ -34,8 +34,8 @@ class OS
{
public:
/* Create an OS interface for this virtual space. If there is no data
loaded in ROM or the OS can't be identified, the type os OS is set to
UNKNOWN and no information is provided. */
loaded in ROM or the OS can't be identified, the type os OS is set to
UNKNOWN and no information is provided. */
OS(VirtualSpace &space);
/* Type of OS, determined at construction */

View File

@ -45,7 +45,6 @@
#define FXOS_PASSES_CFG_H
#include <fxos/disassembly.h>
#include <fxos/passes/pcrel.h>
#include <set>
namespace FxOS {
@ -70,8 +69,6 @@ private:
uint32_t m_lastFunction;
/* Set of instructions in a function, used to generate new claims */
std::set<uint32_t> m_claimedInstructions;
/* pcrel pass used to find call to other functions */
PcrelPass m_pcrel;
};
} /* namespace FxOS */

View File

@ -87,7 +87,7 @@ struct BitfieldType: public BaseType
should equal the size of the array type. */
struct ArrayType: public BaseType
{
class DataType *object_type;
struct DataType *object_type;
int elements;
};

View File

@ -21,7 +21,6 @@
#include <optional>
#include <string>
#include <vector>
#include <cstdint>
namespace FxOS {
@ -35,40 +34,6 @@ struct Symbol
/* Symbol name, no particular conventions */
std::string name;
bool operator<(const FxOS::Symbol &right) const
{
return (type < right.type)
|| (value < right.value && type == right.type);
}
bool operator>(const FxOS::Symbol &right) const
{
return (type > right.type)
|| (value > right.value && type == right.type);
}
bool operator==(const FxOS::Symbol &right) const
{
return value == right.value && type == right.type;
}
bool operator!=(const FxOS::Symbol &right) const
{
return value != right.value || type != right.type;
}
bool operator>=(const FxOS::Symbol &right) const
{
return (type > right.type)
|| (value >= right.value && type == right.type);
}
bool operator<=(const FxOS::Symbol &right) const
{
return (type < right.type)
|| (value <= right.value && type == right.type);
}
};
/* A symbol table, usually the set of symbols of a virtual space */

View File

@ -4,10 +4,7 @@
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
// fxos/util/Queue: Simple queue that handles recursion
//
// Can be instantiated for any T for which std::set<T> is valid and properly
// checks objects' identity.
// fxos/util/Queue: Simple queue that handles recursivity
//---
#ifndef FXOS_UTIL_QUEUE_H

View File

@ -28,14 +28,14 @@ auto constexpr Bottom = RelConst::Bottom;
return bottom(); \
}
RelConst RelConstDomain::bottom() const noexcept
inline RelConst RelConstDomain::bottom() const noexcept
{
RelConst b {};
b.spe = Bottom;
return b;
}
RelConst RelConstDomain::top() const noexcept
inline RelConst RelConstDomain::top() const noexcept
{
RelConst b {};
b.spe = Top;
@ -300,17 +300,12 @@ std::string RelConst::str() const noexcept
if(ival >= -256 && ival < 256) {
uint32_t v = 0;
if(ival >= 0) {
if(str.size())
str += "+";
v = ival;
}
else {
str += "-";
v = -ival;
}
if(str.size() && ival > 0)
str += "+", v = ival;
if(str.size() && ival < 0)
str += "-", v = -ival;
return str + format("%d (0x%08x)", v, uval);
return str + format("%d", v);
}
else {
return str + format("0x%08x", uval);

View File

@ -51,14 +51,6 @@ Instruction::Instruction(uint16_t opcode):
{
}
//---
// Function information
//---
Function::Function(uint32_t pc): address {pc}
{
}
//---
// Dynamic claims
//---
@ -73,12 +65,6 @@ bool Claim::intersects(Claim const &other) const
return inter_start < inter_end;
}
bool Claim::operator==(Claim const &other) const
{
return this->address == other.address && this->size == other.size
&& this->type == other.type && this->owner == other.owner;
}
std::string Claim::str() const
{
std::string details = format(" (claim 0x%08x:%d)", address, size);
@ -154,17 +140,7 @@ Function *Disassembly::getFunctionAt(uint32_t pc)
return &it->second;
}
Function *Disassembly::getOrCreateFunctionAt(uint32_t pc)
{
if(!this->hasFunctionAt(pc)) {
Function f(pc);
this->functions.insert({pc, f});
}
return this->getFunctionAt(pc);
}
std::vector<Claim const *> Disassembly::findClaimConflicts(
uint32_t address, int size, int max)
Claim const *Disassembly::findClaimConflict(uint32_t address, int size)
{
Claim fake_claim = {
.address = address,
@ -172,7 +148,6 @@ std::vector<Claim const *> Disassembly::findClaimConflicts(
.type = 0,
.owner = 0,
};
std::vector<Claim const *> conflicts;
/* Find the first claim whose start is [> address] */
auto it = this->claims.upper_bound(fake_claim);
@ -180,26 +155,19 @@ std::vector<Claim const *> Disassembly::findClaimConflicts(
if(it != this->claims.begin())
it--;
while(it != this->claims.end()
&& (max < 0 || conflicts.size() < (size_t)max)) {
while(it != this->claims.end()) {
/* We completely passed address+size, no conflict found */
if(it->address >= address + size)
break;
return nullptr;
/* There is an intersection */
if(it->intersects(fake_claim))
conflicts.push_back(&*it);
return &*it;
it++;
}
return conflicts;
}
Claim const *Disassembly::findClaimConflict(uint32_t address, int size)
{
auto claims = findClaimConflicts(address, size, 1);
return claims.size() > 0 ? claims[0] : nullptr;
return nullptr;
}
Claim const *Disassembly::getClaimAt(uint32_t address)
@ -209,35 +177,15 @@ Claim const *Disassembly::getClaimAt(uint32_t address)
bool Disassembly::addExclusiveClaim(Claim const &c)
{
auto conflicts = this->findClaimConflicts(c.address, c.size);
bool exclusive = true;
for(auto conflict: conflicts) {
/* Allow declaring the same claim twice */
if(*conflict == c)
continue;
Claim const *conflict = this->findClaimConflict(c.address, c.size);
if(conflict) {
FxOS_log(ERR, "exclusive claim for %s conflicts with %s", c.str(),
conflicts[0]->str());
exclusive = false;
conflict->str());
return false;
}
if(exclusive)
this->claims.insert(c);
return exclusive;
}
std::vector<Claim const *> Disassembly::findClaimsOwnedBy(uint32_t address)
{
std::vector<Claim const *> claims;
/* Since we don't order by owner we have to tank the linear search */
for(auto const &c: this->claims) {
if(c.owner == address)
claims.push_back(&c);
}
return claims;
this->claims.insert(c);
return true;
}

View File

@ -261,12 +261,6 @@ bool AsmInstruction::iscondjump() const noexcept
return false;
}
bool AsmInstruction::iscall() const noexcept
{
return !strcmp(mnemonic, "jsr") || !strcmp(mnemonic, "bsr")
|| !strcmp(mnemonic, "bsrf");
}
bool AsmInstruction::isdelayed() const noexcept
{
char const *v[] = {
@ -294,7 +288,6 @@ bool AsmInstruction::isdelayed() const noexcept
bool AsmInstruction::isvaliddelayslot() const noexcept
{
// TODO: PC-relative move is a valid delay slot but it doesn't work
return !isdelayed() && !isterminal() && !isjump() && !iscondjump()
&& strcmp(this->mnemonic, "mova") != 0;
}

View File

@ -13,7 +13,7 @@
namespace FxOS {
CfgPass::CfgPass(Disassembly &disasm):
InstructionPass(disasm), m_claimedInstructions {}, m_pcrel {disasm}
InstructionPass(disasm), m_claimedInstructions {}
{
this->setAllowDiscovery(true);
}
@ -94,7 +94,6 @@ bool CfgPass::analyzeInstruction(uint32_t pc, Instruction &i)
i.jmptarget = jmptarget;
}
m_pcrel.analyzeInstruction(pc, i);
return true;
}
@ -103,35 +102,13 @@ bool CfgPass::exploreFunction(uint32_t pc)
m_lastFunction = pc;
m_claimedInstructions.clear();
Function *func = m_disasm.getOrCreateFunctionAt(pc);
if(!this->analyzeFunction(pc))
return false;
RelConstDomain RCD;
/* Look for call targets */
for(uint32_t pc: m_claimedInstructions) {
Instruction const *ci = m_disasm.getInstructionAt(pc);
if(!ci)
continue;
AsmInstruction const &i = *ci->inst;
/* Find function call instructions */
if(i.isterminal() || !i.iscall() || i.arg_count < 1)
continue;
/* The target must be known */
if(!RCD.is_constant(ci->args[0].location))
continue;
uint32_t target = RCD.constant_value(ci->args[0].location);
auto &v = func->callTargets;
if(std::find(v.begin(), v.end(), target) == v.end())
func->callTargets.push_back(target);
if(!m_disasm.hasFunctionAt(pc)) {
// TODO: Have proper function creation methods in Disassembly
Function func = {.address = pc, .callTargets = {}};
m_disasm.functions[pc] = func;
}
return true;
return this->analyzeFunction(pc);
}
std::set<Claim> CfgPass::resultClaims()

View File

@ -50,6 +50,20 @@ static void ad_disassemble_all(
printf("\n");
FxOS_log(LOG, "Finished pass <cfg> in %s", timer.format_time());
/* Annotate all decoded instructions with pcrel/syscall
TODO: analyze only the functions, if possible */
printr("[pcrel] Resolving PC-relative addressing modes...");
timer.restart();
PcrelPass pcrel_pass(space.disasm);
if(!pcrel_pass.analyzeAllInstructions()) {
errors++;
if(!force)
return;
}
timer.stop();
printf("\n");
FxOS_log(LOG, "Finished pass <pcrel> in %s", timer.format_time());
printr("[syscall] Finding syscall references...");
timer.restart();
OS *os = space.os_analysis();
@ -128,103 +142,6 @@ void _ads(Session &session)
ad_disassemble_all(space, addresses, true);
}
//---
// am
//---
static void _am_cg_main_menu_function(VirtualSpace &vspace)
{
OS *os = vspace.os_analysis();
if(!os) {
FxOS_log(ERR, "no OS analysis");
return;
}
if(os->syscall_count() < 0x1e58) {
FxOS_log(ERR, "less than 0x1e58 syscalls");
return;
}
uint32_t sc_addr = os->syscall(0x1e58);
fmt::print("syscall %%1e58 found at 0x{:08x}\n", sc_addr);
/* Check up to 150 instructions to find the call to the internal function
SaveAndOpenMainMenu(). This call is in a widget of the shape
mov.l GetkeyToMainFunctionReturnFlag, rX
mov #3, rY
bsr SaveAndOpenMainMenu
mov.b rY, @rX
bra <start of widget>
nop */
for(int i = 0; i < 150; i++) {
uint16_t i0 = vspace.read_u16(sc_addr + 2 * (i + 0));
uint16_t i1 = vspace.read_u16(sc_addr + 2 * (i + 1));
uint16_t i2 = vspace.read_u16(sc_addr + 2 * (i + 2));
uint16_t i3 = vspace.read_u16(sc_addr + 2 * (i + 3));
uint16_t i4 = vspace.read_u16(sc_addr + 2 * (i + 4));
uint16_t i5 = vspace.read_u16(sc_addr + 2 * (i + 5));
/* Match: mov.l @(disp, pc), rX */
if((i0 & 0xf000) != 0xd000)
continue;
int rX = (i0 >> 8) & 0x0f;
/* Match: mov #3, rY */
if((i1 & 0xf0ff) != 0xe003)
continue;
int rY = (i1 >> 8) & 0x0f;
/* Match: bsr @(disp, pc) */
if((i2 & 0xf000) != 0xb000)
continue;
int disp = (i2 & 0x0fff);
/* Match: mov.b rX, @rY */
if((i3 != 0x2000 + (rX << 8) + (rY << 4)))
continue;
/* Match: bra @(_, pc) */
if((i4 & 0xf000) != 0xa000)
continue;
/* Match: nop */
if(i5 != 0x0009)
continue;
/* Return the target of the bsr instruction */
uint32_t fun_addr = sc_addr + 2 * (i + 2) + 4 + disp * 2;
fmt::print("found widget at 0x{:08x}\n", sc_addr + 2 * i);
fmt::print("rX = r{}, rY = r{}, disp = {}\n", rX, rY, disp);
fmt::print("main menu function address: 0x{:08x}\n", fun_addr);
}
}
static std::string parse_am(Session &session, Parser &parser)
{
if(!session.current_space)
return "";
std::string name = parser.symbol();
parser.end();
return name;
}
void _am(Session &session, std::string name)
{
if(!session.current_space) {
FxOS_log(ERR, "am: no virtual space");
return;
}
if(name == "cg_main_menu_function")
_am_cg_main_menu_function(*session.current_space);
else
FxOS_log(ERR, "am: unknown misc. command '%s'", name);
}
//---
// Command definitions
//---
@ -257,16 +174,3 @@ Disassembles all syscalls entries using ad, which stores the results in the
current virtual space's main disassembly. Unlike ad, this commands continues
even if some syscalls fail to disassemble.
)");
static ShellCommand _am_cmd(
"am",
[](Session &s, Parser &p) {
auto name = parse_am(s, p);
_am(s, name);
},
[](Session &s, Parser &p) { parse_am(s, p); }, "Analysis: Misc functions",
R"(
am <name>
Runs miscellaneous analysis functions; commonly used for prototyping.
)");

View File

@ -69,69 +69,81 @@ static void disassemble(Session &session, Disassembly &disasm,
// d
//---
struct _d_args
static uint32_t parse_d(Session &session, Parser &parser)
{
std::variant<long, Range> location;
};
static _d_args parse_d(Session &session, Parser &parser)
{
_d_args args;
if(!session.current_space)
return {};
return 0;
uint32_t address = session.current_space->cursor;
args.location = parser.at_end()
? session.current_space->cursor
: parser.expr_or_range(session.current_space);
if(!parser.at_end()) {
auto v = parser.expr_or_range(session.current_space);
if(std::holds_alternative<long>(v)) {
address = std::get<long>(v);
}
else {
// TODO: Use an args struct etc. This is placeholder.
address = std::get<Range>(v).start;
}
}
parser.end();
return args;
return address;
}
void _d(Session &session, std::variant<long, Range> location)
void _d(Session &session, uint32_t address)
{
if(!session.current_space)
return;
FxOS::Disassembly disasm(*session.current_space);
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)
disasm.getInstructionAt(pc, true);
disassemble(session, disasm,
{"pcrel", /*"constprop",*/ "syscall", "print"}, -1);
if(address & 1) {
fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n", address,
address + 1);
address++;
}
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++;
}
disassemble(session, disasm,
{"cfg", "pcrel", /*"constprop",*/ "syscall", "print"}, address);
}
/* cfg implicitly does pcrel */
disassemble(session, disasm,
{"cfg", /*"constprop",*/ "syscall", "print"}, address);
//---
// dr
//---
static Range parse_dr(Session &session, Parser &parser)
{
Range range = parser.range(session.current_space);
parser.end();
return range;
}
void _dr(Session &session, Range range)
{
if(!session.current_space)
return;
FxOS::Disassembly disasm(*session.current_space);
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)
disasm.getInstructionAt(pc, true);
disassemble(
session, disasm, {"pcrel", /*"constprop",*/ "syscall", "print"}, -1);
}
//---
@ -139,13 +151,9 @@ void _d(Session &session, std::variant<long, Range> location)
//---
static ShellCommand _d_cmd(
"d",
[](Session &s, Parser &p) {
auto args = parse_d(s, p);
_d(s, args.location);
},
"d", [](Session &s, Parser &p) { _d(s, parse_d(s, p)); },
[](Session &s, Parser &p) { parse_d(s, p); }, "Disassemble", R"(
d [<address|range>]
d [<address>]
Disassembles code starting at the specified address, exploring branches until
function terminators, invalid instructions, or dynamically-computed jumps. The
@ -160,3 +168,15 @@ The following disassembler passes are run:
pcrel Computes PC-relative addresses (eg mov.l, mova, bf, bra...)
syscall Annotates uses of syscall table entries with the syscall number
)");
static ShellCommand _dr_cmd(
"dr", [](Session &s, Parser &p) { _dr(s, parse_dr(s, p)); },
[](Session &s, Parser &p) { parse_dr(s, p); }, "Disassemble Range", R"(
dr [<range>]
Disassembles an explicit region of memory. This is similar to d, except that
the disassembled code is pre-loaded from the region instead of being explored
by the cfg pass. See d? for more information.
Like d, this command does not extend the virtual space's main disassembly.
)");

View File

@ -30,8 +30,8 @@ static _e_args parse_e(Session &session, Parser &parser)
if(!args.space_name.empty()) {
space = session.get_space(args.space_name);
if(!space) {
std::string msg
= format("virtual space '%s' does not exist", args.space_name);
std::string msg =
format("virtual space '%s' does not exist", args.space_name);
if(parser.completing())
throw Parser::CompletionRequest("_error", msg);
else
@ -49,15 +49,14 @@ static _e_args parse_e(Session &session, Parser &parser)
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);
int length = (labs(value) <= (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);
long a = abs(value);
if(a <= 100 || a % 100 <= 1 || a % 100 >= 99)
fmt::print(" = {}", a);
fmt::print("\n");
}

View File

@ -38,10 +38,10 @@ void _h_hexdump(Session &session, Range r, Selections sel)
fmt::print(" ");
}
else if(is_selected(addr, sel)) {
fmt::print(theme(13), "{:02x}", v.read_u8(addr).value);
fmt::print(theme(13), "{:02x}", v.read_u8(addr));
}
else {
fmt::print("{:02x}", v.read_u8(addr).value);
fmt::print("{:02x}", v.read_u8(addr));
}
}

View File

@ -34,69 +34,11 @@ void _ic(Session &session, struct _ic_args const &args)
return;
for(uint32_t address: args.addresses) {
fmt::print("Claim over 0x{:08x}:\n", address);
Claim const *claim = session.current_space->disasm.getClaimAt(address);
if(claim)
fmt::print(" 0x{:08x} is claimed by {}\n", address, claim->str());
fmt::print("0x{:08x} is claimed by {}\n", address, claim->str());
else
fmt::print(" 0x{:08x} is not claimed\n", address);
auto dep = session.current_space->disasm.findClaimsOwnedBy(address);
fmt::print("Claims owned by 0x{:08x}:\n", address);
for(Claim const *c: dep)
fmt::print(" - {}\n", c->str());
if(!dep.size())
fmt::print(" (none)\n");
}
}
//---
// if
//---
struct _if_args
{
std::vector<uint32_t> addresses;
};
static struct _if_args parse_if(Session &session, Parser &parser)
{
_if_args args;
while(!parser.at_end())
args.addresses.push_back(parser.expr(session.current_space));
parser.end();
return args;
}
void _if(Session &session, struct _if_args const &args)
{
if(!session.current_space)
return;
Disassembly &disasm = session.current_space->disasm;
if(!args.addresses.size()) {
fmt::print("{} functions\n", disasm.functions.size());
}
for(uint32_t address: args.addresses) {
Function *func = disasm.getFunctionAt(address);
if(!func) {
FxOS_log(ERR, "no function at 0x{:08x}", address);
continue;
}
// TODO: Promote address to syscall, name, etc.
fmt::print("0x{:08x}:\n", address);
fmt::print(" callTargets:\n");
auto &ct = func->callTargets;
// TODO: Promote address to syscall, name, etc.
for(uint32_t pc: ct)
fmt::print(" 0x{:08x}\n", pc);
if(!ct.size())
fmt::print(" (none)\n");
fmt::print("0x{:08x} is not claimed\n", address);
}
}
@ -307,7 +249,6 @@ struct _is_args
{
std::string vspace_name;
std::optional<FxOS::Symbol> symbol;
bool sort;
};
static struct _is_args parse_is(Session &session, Parser &parser)
@ -317,9 +258,6 @@ static struct _is_args parse_is(Session &session, Parser &parser)
parser.option("vspace",
[&args](std::string const &value) { args.vspace_name = value; });
parser.option("sort",
[&args](std::string const &value) { args.sort = (value == "true"); });
parser.accept_options();
FxOS::Symbol s;
@ -358,7 +296,7 @@ static struct _is_args parse_is(Session &session, Parser &parser)
}
void _is(Session &session, std::string vspace_name,
std::optional<FxOS::Symbol> symbol, bool sort)
std::optional<FxOS::Symbol> symbol)
{
VirtualSpace *space = session.current_space;
if(!space) {
@ -413,9 +351,6 @@ void _is(Session &session, std::string vspace_name,
symbols = {s};
}
if(sort)
std::sort(&symbols[0], &symbols[symbols.size()]);
for(auto const &s: symbols) {
if(s.type == FxOS::Symbol::Syscall) {
fmt::print(theme(10), " %{:04x}", s.value);
@ -442,19 +377,6 @@ usually generated by analysis commands and allow sections of the OS to be
marked as part of functions, data, interrupt handlers, etc.
)");
static ShellCommand _if_cmd(
"if",
[](Session &s, Parser &p) {
auto args = parse_if(s, p);
_if(s, args);
},
[](Session &s, Parser &p) { parse_if(s, p); }, "Info Function", R"(
if [<function>...]
Prints information about functions. Without arguments, prints vspace-level
statistics. With arguments, prints detailed function info.
)");
static ShellCommand _io_cmd(
"io", [](Session &s, Parser &p) { _io(s, parse_io(s, p)); },
[](Session &s, Parser &p) { parse_io(s, p); }, "Info OS", R"(
@ -482,13 +404,12 @@ static ShellCommand _is_cmd(
"is",
[](Session &s, Parser &p) {
auto args = parse_is(s, p);
_is(s, args.vspace_name, args.symbol, args.sort);
_is(s, args.vspace_name, args.symbol);
},
[](Session &s, Parser &p) { parse_is(s, p); }, "Info Symbols", R"(
is [sort=true] [vspace=<virtual_space>] [<address|syscall>]
is [vspace=<virtual_space>] [<address|syscall>]
Lists symbols in the specified virtual space (defaults to the current
one). By default, all symbols are listed, but if an address or syscall is
provided, the symbol associated with it will be printed instead. If sort=true,
symbols will be sorted by syscall number and then address.
provided, the symbol associated with it will be printed instead.
)");

View File

@ -424,15 +424,7 @@ int main(int argc, char **argv)
}
/* Exhaust command input (if not all used by the command) */
while(true) {
try {
parser.exhaust_until_separator();
break;
}
catch(std::exception &e) {
FxOS_log(ERR, "%s", e.what());
}
}
parser.exhaust_until_separator();
}
/* Save command history */

View File

@ -249,12 +249,12 @@ std::variant<long, Range> Parser::expr_or_range(VirtualSpace *space)
if(m_la.type == ':') {
expect(':');
long length = expr(space);
return (Range) {start, start + length};
return (Range){start, start + length};
}
else if(m_la.type == '.') {
expect('.');
long end = expr(space);
return (Range) {start, end};
return (Range){start, end};
}
else {
return (long)start;

View File

@ -6,7 +6,6 @@
#include <fxos/symbols.h>
#include <fmt/core.h>
#include <endian.h>
//---
// sh