X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcommandinterpreter.cpp;h=b8a10a99d03cb0f30a4048c4754f370d42f09f8b;hb=a34325fadec5b2be003bf9af1f081bfc4c83e8b6;hp=71e8ee7a001b7eafc14b1ec4f014ff47a48bac84;hpb=c6b2f7585d51164dc32f4dd2a05855913e464c58;p=gldbg.git diff --git a/source/commandinterpreter.cpp b/source/commandinterpreter.cpp index 71e8ee7..b8a10a9 100644 --- a/source/commandinterpreter.cpp +++ b/source/commandinterpreter.cpp @@ -1,32 +1,62 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - -#include -#include -#include -#include +#include +#include +#include +#include +#include "breakpoint.h" #include "commandinterpreter.h" +#include "enums.h" +#include "functions.h" #include "gldbg.h" #include "tracer.h" using namespace std; -using namespace Msp; CommandInterpreter::CommandInterpreter(GlDbg &d): gldbg(d) { - commands["run"] = &CommandInterpreter::cmd_run; - commands["continue"] = &CommandInterpreter::cmd_continue; - commands["c"] = &CommandInterpreter::cmd_continue; - commands["kill"] = &CommandInterpreter::cmd_kill; - commands["signal"] = &CommandInterpreter::cmd_signal; - commands["exit"] = &CommandInterpreter::cmd_exit; - commands["quit"] = &CommandInterpreter::cmd_exit; - commands["trace"] = &CommandInterpreter::cmd_trace; + register_command("help", this, &CommandInterpreter::cmd_help) + .set_help("Provides help on commands", + "help\n" + " Displays a list of commands\n\n" + "help COMMAND\n" + " Gives detailed information on a command\n"); + register_command("exit", this, &CommandInterpreter::cmd_exit) + .set_help("Ends the debugging session"); + commands["quit"] = new CommandAlias(commands["exit"]); + + register_command("run", this, &CommandInterpreter::cmd_run) + .set_help("Starts the program"); + register_command("break", this, &CommandInterpreter::cmd_break) + .set_help("Sets a breakpoint", + "break FUNC\n" + " Makes program execution stop at FUNC\n"); + register_command("unbreak", this, &CommandInterpreter::cmd_unbreak) + .set_help("Removes a breakpoint", + "unbreak FUNC\n" + " Makes program execution no longer stop at FUNC\n"); + register_command("next", this, &CommandInterpreter::cmd_next) + .set_help("Resumes program execution until the next function call"); + commands["step"] = new CommandAlias(commands["next"]); + register_command("finish", this, &CommandInterpreter::cmd_finish) + .set_help("Resumes program execution until the next function return"); + register_command("continue", this, &CommandInterpreter::cmd_continue) + .set_help("Resumes program execution"); + register_command("kill", this, &CommandInterpreter::cmd_kill) + .set_help("Terminates the program immediately"); + register_command("signal", this, &CommandInterpreter::cmd_signal) + .set_help("Resumes execution with a signal", + "signal NUM\n" + "signal NAME\n" + " Sends the signal identified by NUM or NAME to the program and resumes\n" + " execution. Currently recognized signal names are HUP, INT, TERM, SEGV\n" + " and TERM.\n"); + +} + +CommandInterpreter::~CommandInterpreter() +{ + for(CommandMap::iterator i=commands.begin(); i!=commands.end(); ++i) + delete i->second; } void CommandInterpreter::execute(const string &cmd) @@ -35,35 +65,107 @@ void CommandInterpreter::execute(const string &cmd) string name = cmd.substr(0, space); CommandMap::const_iterator i = commands.lower_bound(name); if(i==commands.end() || i->first.compare(0, name.size(), name)) - throw KeyError("Unknown command", name); + throw runtime_error("Unknown command "+name); if(i->first!=name) { CommandMap::const_iterator j = i; if((++j)!=commands.end() && !j->first.compare(0, name.size(), name)) - throw KeyError("Ambiguous command", name); + throw runtime_error("Ambiguous command "+name); } string args; if(space!=string::npos) args = cmd.substr(space+1); - (this->*(i->second))(args); + i->second->execute(args); } +void CommandInterpreter::cmd_help(const string &args) +{ + if(args.empty()) + { + for(CommandMap::const_iterator i=commands.begin(); i!=commands.end(); ++i) + if(!dynamic_cast(i->second)) + printf("%-10s : %s\n", i->first.c_str(), i->second->get_description().c_str()); + } + else + { + CommandMap::const_iterator i = commands.find(args); + if(i==commands.end()) + throw runtime_error("Unknown command "+args); + + const Command *cmd = i->second; + while(const CommandAlias *alias = dynamic_cast(cmd)) + cmd = alias->get_target(); + + printf("%s : %s\n", i->first.c_str(), cmd->get_description().c_str()); + if(!cmd->get_help().empty()) + printf("\n%s", cmd->get_help().c_str()); + } +} void CommandInterpreter::cmd_run(const string &) { gldbg.launch(); } +void CommandInterpreter::cmd_break(const string &args) +{ + unsigned short func = get_function(args.c_str()); + if(!func) + throw runtime_error("Unknown function"); + + gldbg.set_breakpoint(func, BREAK_CALL, 0); +} + +void CommandInterpreter::cmd_unbreak(const string &args) +{ + unsigned short func = get_function(args.c_str()); + if(!func) + throw runtime_error("Unknown function"); + + gldbg.clear_breakpoint(func, BREAK_CALL, 0); +} + +void CommandInterpreter::cmd_next(const string &) +{ + gldbg.set_breakpoint(0, BREAK_CALL, 0); + gldbg.get_process().resume(); +} + +void CommandInterpreter::cmd_finish(const string &) +{ + gldbg.set_breakpoint(0, BREAK_RETURN, 0); + gldbg.get_process().resume(); +} + void CommandInterpreter::cmd_continue(const string &) { + printf("Continuing.\n"); gldbg.get_process().resume(); } void CommandInterpreter::cmd_signal(const string &args) { - gldbg.get_process().resume(lexical_cast(args)); + unsigned sig = 0; + if(args=="HUP" || args=="SIGHUP") + sig = SIGHUP; + else if(args=="INT" || args=="SIGINT") + sig = SIGINT; + else if(args=="ILL" || args=="SIGILL") + sig = SIGILL; + else if(args=="SEGV" || args=="SIGSEGV") + sig = SIGSEGV; + else if(args=="TERM" || args=="SIGTERM") + sig = SIGTERM; + else + { + char *end; + sig = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid signal specification"); + } + gldbg.get_process().resume(sig); } void CommandInterpreter::cmd_kill(const string &) @@ -73,42 +175,40 @@ void CommandInterpreter::cmd_kill(const string &) void CommandInterpreter::cmd_exit(const string &) { - gldbg.quit(); -} - -void CommandInterpreter::cmd_trace(const string &args) -{ - Tracer &tracer = gldbg.get_tracer(); - if(args[0]=='>') + if(gldbg.get_process().get_state()!=Process::INACTIVE) { - string fn = args.substr(1); - if(fn=="-") + printf("Program is still running. Kill it?\n"); + char *answer = readline("[y/n] "); + if(answer[0]=='y') { - tracer.set_output(IO::cout); - IO::print("Tracing to stdout\n"); + gldbg.get_process().kill(); + gldbg.quit(true); } else - { - tracer.set_output(new IO::File(fn, IO::M_WRITE)); - IO::print("Tracing to %s\n", fn); - } + printf("Not confirmed.\n"); } else - { - if(args=="on") - { - tracer.enable(); - IO::print("Tracing enabled\n"); - } - else if(args=="off") - { - tracer.disable(); - IO::print("Tracing disabled\n"); - } - else if(args=="end") - { - tracer.set_output(0); - IO::print("Tracing terminated\n"); - } - } + gldbg.quit(false); +} + + +void CommandInterpreter::Command::set_help(const string &d) +{ + description = d; +} + +void CommandInterpreter::Command::set_help(const string &d, const string &h) +{ + description = d; + help = h; +} + + +CommandInterpreter::CommandAlias::CommandAlias(Command *t): + target(t) +{ } + +void CommandInterpreter::CommandAlias::execute(const string &a) +{ + target->execute(a); }