forked from Lephenixnoir/fxos
add command help messages
This commit is contained in:
parent
bd5e1f918c
commit
4e76ff3a24
61
shell/a.cpp
61
shell/a.cpp
|
@ -213,18 +213,51 @@ void _af4(Session &session, uint32_t value, std::vector<MemoryRegion> ®ions)
|
|||
_afh(session, (char *)&value_big_endian, pattern, 4, 4, -1, regions);
|
||||
}
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("af4",
|
||||
[](Session &s, Parser &p){
|
||||
auto args = parse_af4(s, p);
|
||||
_af4(s, args.value, args.regions); },
|
||||
[](Session &s, Parser &p){ parse_af4(s, p); });
|
||||
static ShellCommand _af4_cmd("af4",
|
||||
[](Session &s, Parser &p){
|
||||
auto args = parse_af4(s, p);
|
||||
_af4(s, args.value, args.regions); },
|
||||
[](Session &s, Parser &p){ parse_af4(s, p); },
|
||||
"Analysis Find 4-aligned value", R"(
|
||||
af4 <value> [<regions>...]
|
||||
|
||||
shell_register_command("afh",
|
||||
[](Session &s, Parser &p) {
|
||||
auto args = parse_afh(s, p);
|
||||
_afh(s, args.reference.c_str(), args.pattern.c_str(), args.size,
|
||||
args.align, args.distance, args.regions); },
|
||||
[](Session &s, Parser &p){ parse_afh(s, p); });
|
||||
}
|
||||
Searches mapped memory for a 4-aligned 32-bit value. If regions are specified
|
||||
(by name or the <start>:<size> syntax), searches these regions. Otherwise,
|
||||
searches every binding in the current virtual space.
|
||||
|
||||
af4 0xb4000000 ROM 0x88000000:512
|
||||
Searches occurrences of 0xb4000000, 4-aligned, within mapped ROM and within
|
||||
the first 512 bytes of RAM.
|
||||
|
||||
af4 0x43415349
|
||||
Seacrhes for the 4-aligned string "CASI" in all currently bound regions.
|
||||
)");
|
||||
|
||||
static ShellCommand _afh_cmd("afh",
|
||||
[](Session &s, Parser &p) {
|
||||
auto args = parse_afh(s, p);
|
||||
_afh(s, args.reference.c_str(), args.pattern.c_str(), args.size,
|
||||
args.align, args.distance, args.regions); },
|
||||
[](Session &s, Parser &p){ parse_afh(s, p); },
|
||||
"Analysis Find Hexadecimal pattern", R"(
|
||||
afh [align=<value>] "<pattern>" [<regions>...]
|
||||
|
||||
Searches mapped memory for a hexadecimal pattern with hole bytes. The pattern
|
||||
should be a hexadecimal string like "0123..6789..cd", consisting either of
|
||||
explicit hexadecimal values or hole bytes marked by "..". The holes must start
|
||||
and end at byte boundaries.
|
||||
|
||||
An occurrence of the pattern is any sequence of bytes that matches the explicit
|
||||
bytes exactly, with no constraint on the hole bytes (ie. any value matches).
|
||||
|
||||
If regions are specified, searches these regions. Otherwise, searches every
|
||||
binding in the current virtual space. If align=<align> is specified, only
|
||||
considers addresses that are multiples of the specified alignment value.
|
||||
|
||||
afh "434153494f......00" ROM
|
||||
Searches strings ending with "CASIO" followed by up to 3 characters in ROM.
|
||||
|
||||
afh align=4 "b4..0000"
|
||||
Searches 4-aligned values close to the display interface 0xb4000000 within
|
||||
all currently bound regions.
|
||||
)");
|
||||
|
|
46
shell/d.cpp
46
shell/d.cpp
|
@ -147,17 +147,39 @@ void _dtl(Session &, std::string filename)
|
|||
// Command registration
|
||||
//---
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("d",
|
||||
[](Session &s, Parser &p){ _d(s, parse_d(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_d(s, p); });
|
||||
static ShellCommand _d_cmd("d",
|
||||
[](Session &s, Parser &p){ _d(s, parse_d(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_d(s, p); },
|
||||
"Disassemble", R"(
|
||||
d [<address>]
|
||||
|
||||
shell_register_command("dr",
|
||||
[](Session &s, Parser &p){ _dr(s, parse_dr(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_dr(s, p); });
|
||||
Disassembles code starting at the specified address, exploring branches until
|
||||
function terminators, invalid instructions, or dynamically-computed jumps. The
|
||||
default address is $ (the cursor of the current virtual space).
|
||||
|
||||
shell_register_command("dtl",
|
||||
[](Session &s, Parser &p){ _dtl(s, parse_dtl(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_dtl(s, p); });
|
||||
}
|
||||
The following disassembler passes are run:
|
||||
cfg Explores the code reachable from the start address
|
||||
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.
|
||||
)");
|
||||
|
||||
static ShellCommand _dtl_cmd("dtl",
|
||||
[](Session &s, Parser &p){ _dtl(s, parse_dtl(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_dtl(s, p); },
|
||||
"Disassembly Table Load", R"(
|
||||
dtl "<file>"
|
||||
|
||||
Loads a disassembly table from the specified file. This command is mostly
|
||||
designed to be used in startup scripts.
|
||||
)");
|
||||
|
|
42
shell/e.cpp
42
shell/e.cpp
|
@ -98,15 +98,35 @@ void _ev(Session &, std::string, std::vector<long> const &values)
|
|||
}
|
||||
}
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("e",
|
||||
[](Session &s, Parser &p){ _e(s, parse_e(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_e(s, p); });
|
||||
static ShellCommand _e_cmd("e",
|
||||
[](Session &s, Parser &p){ _e(s, parse_e(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_e(s, p); },
|
||||
"Evaluate expression", R"(
|
||||
e [<expression>...]
|
||||
|
||||
shell_register_command("ev",
|
||||
[](Session &s, Parser &p){
|
||||
auto const &args = parse_ev(s, p);
|
||||
_ev(s, args.space_name, args.values); },
|
||||
[](Session &s, Parser &p){ parse_ev(s, p); });
|
||||
}
|
||||
Evaluates the specified expressions. The expressions may include syscall
|
||||
references (%0ab), named symbols (TRA), the current cursor ($), and
|
||||
arithmetic expressions.
|
||||
|
||||
The parser doesn't accept arithmetic expressions directly on the command-line;
|
||||
they must be placed within parentheses.
|
||||
|
||||
The resulting values undergo a simple analysis which recovers symbol names and
|
||||
syscall addresses.
|
||||
|
||||
e TRA ($+2)
|
||||
Evaluate the address of the TRA register, and the address of the next
|
||||
instruction.
|
||||
)");
|
||||
|
||||
static ShellCommand _ev_cmd("ev",
|
||||
[](Session &s, Parser &p){
|
||||
auto const &args = parse_ev(s, p);
|
||||
_ev(s, args.space_name, args.values); },
|
||||
[](Session &s, Parser &p){ parse_ev(s, p); },
|
||||
"Evaluate expression in Virtual space", R"(
|
||||
ev <virtual_space> [<expression>...]
|
||||
|
||||
Same as e, but resolves symbols within the named virtual space rather than the
|
||||
current one. See e? for more information.
|
||||
)");
|
||||
|
|
14
shell/g.cpp
14
shell/g.cpp
|
@ -22,9 +22,11 @@ void _g(Session &session, long value)
|
|||
session.current_space->cursor = (value & 0xffffffff);
|
||||
}
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("g",
|
||||
[](Session &s, Parser &p){ _g(s, parse_g(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_g(s, p); });
|
||||
}
|
||||
static ShellCommand _g_cmd("g",
|
||||
[](Session &s, Parser &p){ _g(s, parse_g(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_g(s, p); },
|
||||
"Goto address", R"(
|
||||
g <address>
|
||||
|
||||
Moves the cursor of the current virtual space to the specified address.
|
||||
)");
|
||||
|
|
15
shell/h.cpp
15
shell/h.cpp
|
@ -78,9 +78,12 @@ void _h(Session &session, Range r)
|
|||
_h_hexdump(session, r, {});
|
||||
}
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("h",
|
||||
[](Session &s, Parser &p){ _h(s, parse_h(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_h(s, p); });
|
||||
}
|
||||
static ShellCommand _h_cmd("h",
|
||||
[](Session &s, Parser &p){ _h(s, parse_h(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_h(s, p); },
|
||||
"Hexdump", R"(
|
||||
h (<address>|<range>)
|
||||
|
||||
Dumps the specified range into hexadecimal and ASCII representations. When an
|
||||
address is specified, defaults to a length of 128.
|
||||
)");
|
||||
|
|
36
shell/i.cpp
36
shell/i.cpp
|
@ -111,7 +111,7 @@ static struct _is_args parse_is(Session &, Parser &parser)
|
|||
});
|
||||
|
||||
parser.accept_options();
|
||||
std::string name = parser.at_end() ? "" : parser.symbol("vspace_name");
|
||||
args.vspace_name = parser.at_end() ? "" : parser.symbol("vspace_name");
|
||||
parser.accept_options();
|
||||
|
||||
parser.end();
|
||||
|
@ -136,6 +136,8 @@ void _is(Session &session, std::string vspace_name, bool sort)
|
|||
if(!space)
|
||||
return;
|
||||
|
||||
// TODO: is <vspace_name> doesn't work
|
||||
|
||||
OS *os = space->os_analysis();
|
||||
if(!os) throw CommandError("os analysis on '{}' failed", vspace_name);
|
||||
|
||||
|
@ -160,15 +162,25 @@ void _is(Session &session, std::string vspace_name, bool sort)
|
|||
// Command registration
|
||||
//---
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("io",
|
||||
[](Session &s, Parser &p){ _io(s, parse_io(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_io(s, p); });
|
||||
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"(
|
||||
io [<vspace_name>]
|
||||
|
||||
shell_register_command("is",
|
||||
[](Session &s, Parser &p){
|
||||
auto args = parse_is(s, p);
|
||||
_is(s, args.vspace_name, args.sort); },
|
||||
[](Session &s, Parser &p){ parse_is(s, p); });
|
||||
}
|
||||
Prints information about the OS mapped in the named virtual space (defaults to
|
||||
the current one). This usually requires an OS binary to be mapped to ROM.
|
||||
)");
|
||||
|
||||
static ShellCommand _is_cmd("is",
|
||||
[](Session &s, Parser &p){
|
||||
auto args = parse_is(s, p);
|
||||
_is(s, args.vspace_name, args.sort); },
|
||||
[](Session &s, Parser &p){ parse_is(s, p); },
|
||||
"Info Syscalls", R"(
|
||||
is [sort=true] [<vspace_name>]
|
||||
|
||||
Prints the syscall table for the specified virtual space (defaults to the
|
||||
current one). By default, syscalls are enumerated by syscall number. If
|
||||
sort=true is specified, they are instead sorted by address.
|
||||
)");
|
||||
|
|
|
@ -188,6 +188,7 @@ space [ \t]+
|
|||
<*>{syscall} { yylval.NUM = strtoul(yytext+1, NULL, 16); return T::SYSCALL; }
|
||||
<*>{num} { yylval.NUM = parse_num(yytext); return T::NUM; }
|
||||
<*>{symbol} { yylval.SYMBOL = strdup(yytext); return T::SYMBOL; }
|
||||
<*>"?" { return '?'; }
|
||||
|
||||
/* Generic error and word boundaries violations */
|
||||
<*>{syscall}{letter} { err("invalid syscall number '%s'", yytext); }
|
||||
|
|
|
@ -16,17 +16,22 @@
|
|||
#include "parser.h"
|
||||
#include "commands.h"
|
||||
|
||||
struct CommandSpec {
|
||||
ShellFunction function;
|
||||
ShellCompleter completer;
|
||||
};
|
||||
static std::map<std::string, ShellCommand *> commands;
|
||||
|
||||
static std::map<std::string, CommandSpec> commands;
|
||||
|
||||
void shell_register_command(std::string name, ShellFunction function,
|
||||
ShellCompleter completer)
|
||||
ShellCommand::ShellCommand(std::string _name, ShellFunction _function,
|
||||
ShellCompleter _completer, std::string _shortd, std::string _longd):
|
||||
function {_function}, completer {_completer},
|
||||
short_description {_shortd}
|
||||
{
|
||||
commands[name] = (CommandSpec){ function, completer };
|
||||
/* Left trim */
|
||||
_longd.erase(0, _longd.find_first_not_of("\n"));
|
||||
/* Right trim */
|
||||
int r = _longd.size();
|
||||
while(r > 0 && _longd[--r] == '\n') {}
|
||||
_longd.erase(r+1, _longd.size());
|
||||
|
||||
this->long_description = _longd;
|
||||
commands[_name] = this;
|
||||
}
|
||||
|
||||
static Session global_session;
|
||||
|
@ -84,23 +89,21 @@ Parser::CompletionRequest parse_until_autocomplete(Session &session,
|
|||
Parser p(true);
|
||||
p.start();
|
||||
|
||||
/* Read commands until hitting an unfinished one */
|
||||
/* Read commands until the parser runs out of input and throws a
|
||||
CompletionRequest */
|
||||
try {
|
||||
do {
|
||||
/* First obtain command name */
|
||||
p.skip_separators();
|
||||
std::string cmd = p.symbol("command");
|
||||
/* Then run parser on that command's completer */
|
||||
if(commands.count(cmd) && commands[cmd].completer)
|
||||
commands[cmd].completer(session, p);
|
||||
|
||||
if(commands.count(cmd) && commands[cmd]->completer)
|
||||
commands[cmd]->completer(session, p);
|
||||
} while(!lex_idle());
|
||||
}
|
||||
catch(Parser::CompletionRequest r) {
|
||||
return r;
|
||||
}
|
||||
catch(Parser::SyntaxError &e) {
|
||||
// fmt::print("Syntax error: {}\n", e.what());
|
||||
/* Ignore syntax errors, just don't autocomplete */
|
||||
}
|
||||
|
||||
return Parser::CompletionRequest("", "");
|
||||
|
@ -129,6 +132,7 @@ char *autocomplete(char const *text, int state)
|
|||
|
||||
return (i < options.size()) ? strdup(options[i++].c_str()) : NULL;
|
||||
}
|
||||
|
||||
//---
|
||||
// Shell routine
|
||||
//---
|
||||
|
@ -186,7 +190,8 @@ static std::string read_interactive(Session const &s, bool &leave)
|
|||
}
|
||||
|
||||
std::string cmd = cmd_ptr;
|
||||
add_history(cmd_ptr);
|
||||
if(strlen(cmd_ptr) > 0)
|
||||
add_history(cmd_ptr);
|
||||
free(cmd_ptr);
|
||||
return cmd;
|
||||
}
|
||||
|
@ -194,13 +199,6 @@ static std::string read_interactive(Session const &s, bool &leave)
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
Session &s = global_session;
|
||||
/* Register a no-op quit command for auto-completion */
|
||||
shell_register_command("q", NULL, NULL);
|
||||
/* Register the include command */
|
||||
shell_register_command(".",
|
||||
[](Session &s, Parser &p) { _dot(s, parse_dot(s, p), false); },
|
||||
[](Session &s, Parser &p) { parse_dot(s, p); });
|
||||
|
||||
theme_builtin("tomorrow-night");
|
||||
|
||||
rl_completion_entry_function = autocomplete;
|
||||
|
@ -276,17 +274,33 @@ int main(int argc, char **argv)
|
|||
/* Read the command name */
|
||||
if(parser.lookahead().type == T::END)
|
||||
continue;
|
||||
if(parser.lookahead().type == '?') {
|
||||
for(auto const &it: commands) {
|
||||
fmt::print(" {:5s} {}\n", it.first,
|
||||
it.second->short_description);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::string cmd = parser.symbol("command");
|
||||
if(cmd == "q") break;
|
||||
|
||||
if(cmd == "q" && parser.lookahead().type != '?')
|
||||
break;
|
||||
if(cmd == "p") {
|
||||
parser.dump_command();
|
||||
}
|
||||
else if(commands.count(cmd))
|
||||
{
|
||||
if(commands[cmd].function) commands[cmd].function(s, parser);
|
||||
else if(commands.count(cmd)) {
|
||||
if(parser.lookahead().type == '?') {
|
||||
fmt::print("{}: {}\n\n{}\n", cmd,
|
||||
commands[cmd]->short_description,
|
||||
commands[cmd]->long_description);
|
||||
continue;
|
||||
}
|
||||
if(commands[cmd]->function)
|
||||
commands[cmd]->function(s, parser);
|
||||
}
|
||||
else {
|
||||
fmt::print("\e[31;1merror:\e[0m unknown command '{}'\n", cmd);
|
||||
}
|
||||
else fmt::print("\e[31;1merror:\e[0m unknown command '{}'\n", cmd);
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
fmt::print("\e[31;1merror:\e[0m {}\n", e.what());
|
||||
|
@ -301,3 +315,17 @@ int main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register a no-op quit command for auto-completion */
|
||||
static ShellCommand _q_cmd("q", NULL, NULL, "Quit", "Quits fxos.");
|
||||
|
||||
/* Register the include command */
|
||||
static ShellCommand _dot_cmd(".",
|
||||
[](Session &s, Parser &p) { _dot(s, parse_dot(s, p), false); },
|
||||
[](Session &s, Parser &p) { parse_dot(s, p); },
|
||||
"Include scripts", R"(
|
||||
. "<script_1>" "<script_2>"...
|
||||
|
||||
Reads file paths from its string arguments, and executes each of them as a
|
||||
sequence of commands in the order of the command line.
|
||||
)");
|
||||
|
|
|
@ -209,7 +209,7 @@ std::string Parser::symbol(std::string category)
|
|||
free(t.value.SYMBOL);
|
||||
|
||||
/* This will throw only if there is no token after, not even spaces */
|
||||
if(m_la.type == T::END)
|
||||
if(m_complete && m_la.type == T::END)
|
||||
throw CompletionRequest(category, sym);
|
||||
|
||||
/* If a space is found, get rid of it */
|
||||
|
|
38
shell/s.cpp
38
shell/s.cpp
|
@ -84,17 +84,31 @@ void _ss(Session &session, Symbol s)
|
|||
// Command registration
|
||||
//---
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("sl",
|
||||
[](Session &s, Parser &p){ parse_sl(s, p); _sl(s); },
|
||||
[](Session &s, Parser &p){ parse_sl(s, p); });
|
||||
static ShellCommand _sl_cmd("sl",
|
||||
[](Session &s, Parser &p){ parse_sl(s, p); _sl(s); },
|
||||
[](Session &s, Parser &p){ parse_sl(s, p); },
|
||||
"Symbol List", R"(
|
||||
sl
|
||||
|
||||
shell_register_command("sa",
|
||||
[](Session &s, Parser &p){ _sa(s, parse_sa(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_sa(s, p); });
|
||||
Lists all symbols in the current virtual space.
|
||||
)");
|
||||
|
||||
shell_register_command("ss",
|
||||
[](Session &s, Parser &p){ _ss(s, parse_ss(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_ss(s, p); });
|
||||
}
|
||||
static ShellCommand _sa_cmd("sa",
|
||||
[](Session &s, Parser &p){ _sa(s, parse_sa(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_sa(s, p); },
|
||||
"Symbol at Address", R"(
|
||||
sa <address> <symbol>
|
||||
|
||||
Defines a new symbol at the specified address in the current virtual space.
|
||||
)");
|
||||
|
||||
static ShellCommand _ss_cmd("ss",
|
||||
[](Session &s, Parser &p){ _ss(s, parse_ss(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_ss(s, p); },
|
||||
"Symbol at Syscall", R"(
|
||||
ss %<hex> <symbol>
|
||||
|
||||
Defines a new symbol at the specified syscall number in the current virtual
|
||||
space. The address is not resolved; the same syscall symbol can be used accross
|
||||
multiple OS versions regardless of where the functions are actually located.
|
||||
)");
|
||||
|
|
|
@ -16,8 +16,15 @@ using ShellFunction = void (*)(Session &session, Parser &parser);
|
|||
/* Type of functions to complete arguments to shell commands */
|
||||
using ShellCompleter = void (*)(Session &session, Parser &parser);
|
||||
|
||||
/* Register a command in the shell */
|
||||
void shell_register_command(std::string name, ShellFunction function,
|
||||
ShellCompleter completer);
|
||||
/* Shell command. The constructor registers it automatically */
|
||||
struct ShellCommand {
|
||||
ShellFunction function;
|
||||
ShellCompleter completer;
|
||||
std::string short_description;
|
||||
std::string long_description;
|
||||
|
||||
ShellCommand(std::string name, ShellFunction function,
|
||||
ShellCompleter completer, std::string shortd, std::string longd);
|
||||
};
|
||||
|
||||
#endif /* FXOS_SHELL_H */
|
||||
|
|
77
shell/v.cpp
77
shell/v.cpp
|
@ -179,29 +179,62 @@ void _vm(Session &session, std::string file, std::vector<MemoryRegion> regions)
|
|||
// Command registration
|
||||
//---
|
||||
|
||||
[[gnu::constructor]] static void _(void)
|
||||
{
|
||||
shell_register_command("vl",
|
||||
[](Session &s, Parser &p) { _vl(s, parse_vl(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_vl(s, p); });
|
||||
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>...]
|
||||
|
||||
shell_register_command("vs",
|
||||
[](Session &s, Parser &p) { _vs(s, parse_vs(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_vs(s, p); });
|
||||
Shows the bound regions of each specified virtual space. If none is specified,
|
||||
shows all the virtual spaces.
|
||||
)");
|
||||
|
||||
shell_register_command("vc",
|
||||
[](Session &s, Parser &p) { _vc(s, parse_vc(s, p)); },
|
||||
[](Session &s, Parser &p){ parse_vc(s, p); });
|
||||
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>
|
||||
|
||||
shell_register_command("vct",
|
||||
[](Session &s, Parser &p) {
|
||||
auto const &args = parse_vct(s, p);
|
||||
_vct(s, args.path, args.vspace_name); },
|
||||
[](Session &s, Parser &p){ parse_vct(s, p); });
|
||||
Selects the specified virtual space.
|
||||
)");
|
||||
|
||||
shell_register_command("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); });
|
||||
}
|
||||
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 _vct_cmd("vct",
|
||||
[](Session &s, Parser &p) {
|
||||
auto const &args = parse_vct(s, p);
|
||||
_vct(s, args.path, args.vspace_name); },
|
||||
[](Session &s, Parser &p){ parse_vct(s, p); },
|
||||
"Virtual space Create from Target", R"(
|
||||
vct "<script_file>" [<name>]
|
||||
|
||||
Creates a new virtual space from a script file. If no name is specified, the
|
||||
basename of the script file is used. The new space is created with vc, then the
|
||||
script file is run.
|
||||
)");
|
||||
|
||||
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.
|
||||
)");
|
||||
|
|
Loading…
Reference in New Issue