#include "shell.h" #include "theme.h" #include "parser.h" #include "commands.h" #include "errors.h" #include #include #include using namespace FxOS; //--- // vl //--- static std::vector parse_vl(Session &, Parser &parser) { std::vector 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 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 space = std::make_unique(); session.spaces.emplace(name, std::move(space)); _vs(session, name); _g(session, 0x80000000); } //--- // vm //--- struct _vm_args { std::string path; std::vector 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 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 [...] 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 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 [] 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 "" ... 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. )");