213 lines
5.5 KiB
C++
213 lines
5.5 KiB
C++
#include "shell.h"
|
|
#include "theme.h"
|
|
#include "parser.h"
|
|
#include "commands.h"
|
|
#include "errors.h"
|
|
|
|
#include <fmt/core.h>
|
|
#include <fmt/color.h>
|
|
|
|
#include <fxos/memory.h>
|
|
|
|
using namespace FxOS;
|
|
|
|
//---
|
|
// vl
|
|
//---
|
|
|
|
static std::vector<std::string> parse_vl(Session &, Parser &parser)
|
|
{
|
|
std::vector<std::string> spaces;
|
|
|
|
while(!parser.at_end())
|
|
spaces.push_back(parser.symbol("vspace_name"));
|
|
|
|
parser.end();
|
|
return spaces;
|
|
}
|
|
|
|
static void show_vspace(std::string name, VirtualSpace &s, Session &session)
|
|
{
|
|
bool is_current = (&s == session.current_space);
|
|
|
|
int total_claim_size = 0;
|
|
for(Claim const &c: s.disasm.claims)
|
|
total_claim_size += c.size;
|
|
|
|
if(is_current)
|
|
fmt::print("* ");
|
|
fmt::print(theme(11), "{}\n", name);
|
|
|
|
fmt::print(" Symbol table: {} symbols\n", s.symbols.symbols.size());
|
|
fmt::print(
|
|
" Main disassembly: {} instructions\n", s.disasm.instructions.size());
|
|
fmt::print(" Functions: {}\n", s.disasm.functions.size());
|
|
fmt::print(" Claims: {} (totalling {} bytes)\n", s.disasm.claims.size(),
|
|
total_claim_size);
|
|
|
|
fmt::print(" Region--Start---------End---------File------------------\n");
|
|
if(s.bindings.size() == 0) {
|
|
fmt::print(" (no bindings)\n");
|
|
return;
|
|
}
|
|
for(auto &b: s.bindings) {
|
|
MemoryRegion const *ref = MemoryRegion::region_for(b.region);
|
|
fmt::print(" {:<7s} 0x{:08x} .. 0x{:08x}", (ref ? ref->name : ""),
|
|
b.region.start, b.region.end);
|
|
if(b.buffer.path != "")
|
|
fmt::print(" {}", b.buffer.path);
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
|
|
void _vl(Session &session, std::vector<std::string> const &args)
|
|
{
|
|
if(!args.size()) {
|
|
for(auto &it: session.spaces)
|
|
show_vspace(it.first, *it.second, session);
|
|
}
|
|
else
|
|
for(auto &name: args) {
|
|
VirtualSpace *s = session.get_space(name);
|
|
if(s != nullptr)
|
|
show_vspace(name, *session.spaces[name], session);
|
|
else
|
|
fmt::print("Virtual space '{}' does not exist", name);
|
|
}
|
|
}
|
|
|
|
//---
|
|
// vs
|
|
//---
|
|
|
|
static std::string parse_vs(Session &, Parser &parser)
|
|
{
|
|
std::string name = parser.symbol("vspace_name");
|
|
parser.end();
|
|
return name;
|
|
}
|
|
|
|
void _vs(Session &session, std::string const &name)
|
|
{
|
|
VirtualSpace *s = session.get_space(name);
|
|
if(!s)
|
|
return;
|
|
session.current_space = session.spaces[name].get();
|
|
}
|
|
|
|
//---
|
|
// vc
|
|
//---
|
|
|
|
static std::string parse_vc(Session &, Parser &parser)
|
|
{
|
|
std::string name = "";
|
|
if(!parser.at_end())
|
|
name = parser.symbol();
|
|
parser.end();
|
|
return name;
|
|
}
|
|
|
|
void _vc(Session &session, std::string name)
|
|
{
|
|
if(name == "")
|
|
name = session.generate_space_name("space", true);
|
|
else
|
|
name = session.generate_space_name(name, false);
|
|
|
|
/* Create an empty space and select it */
|
|
std::unique_ptr<VirtualSpace> space = std::make_unique<VirtualSpace>();
|
|
session.spaces.emplace(name, std::move(space));
|
|
_vs(session, name);
|
|
_g(session, 0x80000000);
|
|
}
|
|
|
|
//---
|
|
// vm
|
|
//---
|
|
|
|
struct _vm_args
|
|
{
|
|
std::string path;
|
|
std::vector<MemoryRegion> regions;
|
|
};
|
|
|
|
static _vm_args parse_vm(Session &session, Parser &parser)
|
|
{
|
|
_vm_args args {};
|
|
args.path = parser.str();
|
|
|
|
/* TODO: vm: Allow specifying address without a size */
|
|
do
|
|
args.regions.push_back(parser.region(session.current_space));
|
|
while(!parser.at_end());
|
|
|
|
parser.end();
|
|
return args;
|
|
}
|
|
|
|
void _vm(Session &session, std::string file, std::vector<MemoryRegion> regions)
|
|
{
|
|
if(!session.current_space)
|
|
return;
|
|
|
|
std::string path = session.file(file);
|
|
Buffer contents(path);
|
|
|
|
/* If no files are loaded yet, set the PC to the first loaded region */
|
|
if(!session.current_space->bindings.size())
|
|
session.pc = regions[0].start;
|
|
|
|
for(auto &r: regions)
|
|
session.current_space->bind_region(r, contents);
|
|
}
|
|
|
|
//---
|
|
// Command registration
|
|
//---
|
|
|
|
static ShellCommand _vl_cmd(
|
|
"vl", [](Session &s, Parser &p) { _vl(s, parse_vl(s, p)); },
|
|
[](Session &s, Parser &p) { parse_vl(s, p); }, "Virtual space List", R"(
|
|
vl [<space_name>...]
|
|
|
|
Shows the bound regions of each specified virtual space. If none is specified,
|
|
shows all the virtual spaces.
|
|
)");
|
|
|
|
static ShellCommand _vs_cmd(
|
|
"vs", [](Session &s, Parser &p) { _vs(s, parse_vs(s, p)); },
|
|
[](Session &s, Parser &p) { parse_vs(s, p); }, "Virtual space Select", R"(
|
|
vs <space_name>
|
|
|
|
Selects the specified virtual space.
|
|
)");
|
|
|
|
static ShellCommand _vc_cmd(
|
|
"vc", [](Session &s, Parser &p) { _vc(s, parse_vc(s, p)); },
|
|
[](Session &s, Parser &p) { parse_vc(s, p); }, "Virtual space Create", R"(
|
|
vc [<name>]
|
|
|
|
Creates a new virtual space under the specified name. If such a space already
|
|
exists, adds a numerical suffix like _0 until a fresh name is found. The space
|
|
is created with no bindings and automatically selected.
|
|
)");
|
|
|
|
static ShellCommand _vm_cmd(
|
|
"vm",
|
|
[](Session &s, Parser &p) {
|
|
auto const &args = parse_vm(s, p);
|
|
_vm(s, args.path, args.regions);
|
|
},
|
|
[](Session &s, Parser &p) { parse_vm(s, p); }, "Virtual space Map file", R"(
|
|
vm "<file>" <region>...
|
|
|
|
Maps the named file into all the specified regions of the current virtual
|
|
space. If the file is smaller than the region, it is zero-padded; if the region
|
|
is smaller, the extra data is ignored. The amount of data mapped is always
|
|
exactly the size of the requested region.
|
|
|
|
vm "/os/fx/3.10/3.10.bin" ROM ROM_P2
|
|
Maps a binary file 3.10.bin to ROM, through both P1 and P2.
|
|
)");
|