From: <m97...@us...> - 2008-08-28 18:05:47
|
Revision: 8182 http://openmsx.svn.sourceforge.net/openmsx/?rev=8182&view=rev Author: m9710797 Date: 2008-08-28 18:05:52 +0000 (Thu, 28 Aug 2008) Log Message: ----------- implemented breakpoints on probes Modified Paths: -------------- openmsx/trunk/src/cpu/BreakPoint.cc openmsx/trunk/src/cpu/BreakPoint.hh openmsx/trunk/src/cpu/WatchPoint.cc openmsx/trunk/src/cpu/WatchPoint.hh openmsx/trunk/src/debugger/Debugger.cc openmsx/trunk/src/debugger/Debugger.hh openmsx/trunk/src/debugger/Probe.hh openmsx/trunk/src/debugger/node.mk openmsx/trunk/src/utils/Observer.hh openmsx/trunk/src/utils/Subject.hh Added Paths: ----------- openmsx/trunk/src/debugger/ProbeBreakPoint.cc openmsx/trunk/src/debugger/ProbeBreakPoint.hh Modified: openmsx/trunk/src/cpu/BreakPoint.cc =================================================================== --- openmsx/trunk/src/cpu/BreakPoint.cc 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/cpu/BreakPoint.cc 2008-08-28 18:05:52 UTC (rev 8182) @@ -11,9 +11,9 @@ std::auto_ptr<TclObject> command, std::auto_ptr<TclObject> condition) : BreakPointBase(cliComm, command, condition) + , id(++lastId) , address(address_) { - id = ++lastId; } word BreakPoint::getAddress() const Modified: openmsx/trunk/src/cpu/BreakPoint.hh =================================================================== --- openmsx/trunk/src/cpu/BreakPoint.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/cpu/BreakPoint.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -26,8 +26,8 @@ unsigned getId() const; private: - unsigned id; - word address; + const unsigned id; + const word address; static unsigned lastId; }; Modified: openmsx/trunk/src/cpu/WatchPoint.cc =================================================================== --- openmsx/trunk/src/cpu/WatchPoint.cc 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/cpu/WatchPoint.cc 2008-08-28 18:05:52 UTC (rev 8182) @@ -13,10 +13,10 @@ std::auto_ptr<TclObject> condition, Type type_, unsigned beginAddr_, unsigned endAddr_) : BreakPointBase(cliComm, command, condition) + , id(++lastId) , beginAddr(beginAddr_), endAddr(endAddr_), type(type_) { assert(beginAddr <= endAddr); - id = ++lastId; } WatchPoint::~WatchPoint() Modified: openmsx/trunk/src/cpu/WatchPoint.hh =================================================================== --- openmsx/trunk/src/cpu/WatchPoint.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/cpu/WatchPoint.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -22,7 +22,7 @@ std::auto_ptr<TclObject> command, std::auto_ptr<TclObject> condition, Type type, unsigned beginAddr, unsigned endAddr); - virtual ~WatchPoint(); + virtual ~WatchPoint(); // needed for dynamic_cast unsigned getId() const; Type getType() const; @@ -30,10 +30,10 @@ unsigned getEndAddress() const; private: - unsigned id; - unsigned beginAddr; - unsigned endAddr; - Type type; + const unsigned id; + const unsigned beginAddr; + const unsigned endAddr; + const Type type; static unsigned lastId; }; Modified: openmsx/trunk/src/debugger/Debugger.cc =================================================================== --- openmsx/trunk/src/debugger/Debugger.cc 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/debugger/Debugger.cc 2008-08-28 18:05:52 UTC (rev 8182) @@ -3,6 +3,7 @@ #include "Debugger.hh" #include "Debuggable.hh" #include "Probe.hh" +#include "ProbeBreakPoint.hh" #include "MSXMotherBoard.hh" #include "MSXCPU.hh" #include "MSXCPUInterface.hh" @@ -72,6 +73,12 @@ TclObject& result); void probeRead(const vector<TclObject*>& tokens, TclObject& result); + void probeSetBreakPoint(const vector<TclObject*>& tokens, + TclObject& result); + void probeRemoveBreakPoint(const vector<TclObject*>& tokens, + TclObject& result); + void probeListBreakPoints(const vector<TclObject*>& tokens, + TclObject& result); CliComm& cliComm; Debugger& debugger; @@ -90,6 +97,11 @@ Debugger::~Debugger() { + for (ProbeBreakPoints::const_iterator it = probeBreakPoints.begin(); + it != probeBreakPoints.end(); ++it) { + delete *it; + } + assert(!cpu); assert(debuggables.empty()); } @@ -175,6 +187,49 @@ } +void Debugger::insertProbeBreakPoint(auto_ptr<ProbeBreakPoint> bp) +{ + probeBreakPoints.push_back(bp.release()); +} + +void Debugger::removeProbeBreakPoint(const string& name) +{ + if (StringOp::startsWith(name, "pp#")) { + // remove by id + unsigned id = StringOp::stringToInt(name.substr(3)); + for (ProbeBreakPoints::iterator it = probeBreakPoints.begin(); + it != probeBreakPoints.end(); ++it) { + if ((*it)->getId() == id) { + delete *it; + probeBreakPoints.erase(it); + return; + } + } + throw CommandException("No such breakpoint: " + name); + } else { + // remove by probe, only works for unconditional bp + for (ProbeBreakPoints::iterator it = probeBreakPoints.begin(); + it != probeBreakPoints.end(); ++it) { + if ((*it)->getProbe().getName() == name) { + delete *it; + probeBreakPoints.erase(it); + return; + } + } + throw CommandException( + "No (unconditional) breakpoint for probe: " + name); + } +} + +void Debugger::removeProbeBreakPoint(ProbeBreakPoint& bp) +{ + ProbeBreakPoints::iterator it = + find(probeBreakPoints.begin(), probeBreakPoints.end(), &bp); + assert(it != probeBreakPoints.end()); + delete *it; + probeBreakPoints.erase(it); +} + // class DebugCmd static word getAddress(const vector<TclObject*>& tokens) @@ -607,6 +662,12 @@ probeDesc(tokens, result); } else if (subCmd == "read") { probeRead(tokens, result); + } else if (subCmd == "set_bp") { + probeSetBreakPoint(tokens, result); + } else if (subCmd == "remove_bp") { + probeRemoveBreakPoint(tokens, result); + } else if (subCmd == "list_bp") { + probeListBreakPoints(tokens, result); } else { throw SyntaxError(); } @@ -636,6 +697,65 @@ ProbeBase& probe = debugger.getProbe(tokens[3]->getString()); result.setString(probe.getValue()); } +void DebugCmd::probeSetBreakPoint(const vector<TclObject*>& tokens, + TclObject& result) +{ + auto_ptr<ProbeBreakPoint> bp; + auto_ptr<TclObject> command( + new TclObject(result.getInterpreter(), "debug break")); + auto_ptr<TclObject> condition; + switch (tokens.size()) { + case 6: // command + command->setString(tokens[5]->getString()); + command->checkCommand(); + // fall-through + case 5: // condition + if (!tokens[4]->getString().empty()) { + condition.reset(new TclObject(*tokens[4])); + condition->checkExpression(); + } + // fall-through + case 4: { // probe + ProbeBase& probe = debugger.getProbe(tokens[3]->getString()); + bp.reset(new ProbeBreakPoint(cliComm, command, condition, + debugger, probe)); + break; + } + default: + if (tokens.size() < 4) { + throw CommandException("Too few arguments."); + } else { + throw CommandException("Too many arguments."); + } + } + result.setString("pp#" + StringOp::toString(bp->getId())); + debugger.insertProbeBreakPoint(bp); +} +void DebugCmd::probeRemoveBreakPoint(const vector<TclObject*>& tokens, + TclObject& result) +{ + if (tokens.size() != 4) { + throw SyntaxError(); + } + debugger.removeProbeBreakPoint(tokens[3]->getString()); +} +void DebugCmd::probeListBreakPoints(const vector<TclObject*>& tokens, + TclObject& result) +{ + string res; + for (Debugger::ProbeBreakPoints::const_iterator it = + debugger.probeBreakPoints.begin(); + it != debugger.probeBreakPoints.end(); ++it) { + const ProbeBreakPoint& bp = **it; + TclObject line(result.getInterpreter()); + line.addListElement("pp#" + StringOp::toString(bp.getId())); + line.addListElement(bp.getProbe().getName()); + line.addListElement(bp.getCondition()); + line.addListElement(bp.getCommand()); + res += line.getString() + '\n'; + } + result.setString(res); +} string DebugCmd::help(const vector<string>& tokens) const { @@ -763,9 +883,12 @@ static const string probeHelp = "debug probe <subcommand> [<arguments>]\n" " Possible subcommands are:\n" - " list returns a list of all probes\n" - " desc <probe> returns a description of this probe\n" - " read <probe> returns the current value of this probe\n"; + " list returns a list of all probes\n" + " desc <probe> returns a description of this probe\n" + " read <probe> returns the current value of this probe\n" + " set_bp <probe> [<cond>] [<cmd>] set a breakpoint on the given probe\n" + " remove_bp <id> remove the given reakpoint\n" + " list_bp returns a list of breakpoints that are set on probes\n"; static const string contHelp = "debug cont\n" " Continue execution after CPU was breaked.\n"; @@ -925,13 +1048,17 @@ subCmds.insert("list"); subCmds.insert("desc"); subCmds.insert("read"); + subCmds.insert("set_bp"); + subCmds.insert("remove_bp"); + subCmds.insert("list_bp"); completeString(tokens, subCmds); } } break; case 4: if ((tokens[1] == "probe") && - ((tokens[2] == "desc") || (tokens[2] == "read"))) { + ((tokens[2] == "desc") || (tokens[2] == "read") || + (tokens[2] == "set_bp"))) { set<string> probes; debugger.getDebuggables(probes); completeString(tokens, probes); Modified: openmsx/trunk/src/debugger/Debugger.hh =================================================================== --- openmsx/trunk/src/debugger/Debugger.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/debugger/Debugger.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -4,6 +4,7 @@ #define DEBUGGER_HH #include "noncopyable.hh" +#include <vector> #include <map> #include <set> #include <string> @@ -14,6 +15,7 @@ class MSXMotherBoard; class Debuggable; class ProbeBase; +class ProbeBreakPoint; class MSXCPU; class DebugCmd; @@ -31,6 +33,7 @@ void unregisterProbe(const std::string& name, ProbeBase& probe); ProbeBase* findProbe(const std::string& name); + void removeProbeBreakPoint(ProbeBreakPoint& bp); void setCPU(MSXCPU* cpu); private: @@ -40,14 +43,19 @@ ProbeBase& getProbe(const std::string& name); void getProbes(std::set<std::string>& result) const; + void insertProbeBreakPoint(std::auto_ptr<ProbeBreakPoint> bp); + void removeProbeBreakPoint(const std::string& name); + MSXMotherBoard& motherBoard; friend class DebugCmd; const std::auto_ptr<DebugCmd> debugCmd; typedef std::map<std::string, Debuggable*> Debuggables; typedef std::map<std::string, ProbeBase*> Probes; + typedef std::vector<ProbeBreakPoint*> ProbeBreakPoints; Debuggables debuggables; - Probes probes; + Probes probes; + ProbeBreakPoints probeBreakPoints; MSXCPU* cpu; }; Modified: openmsx/trunk/src/debugger/Probe.hh =================================================================== --- openmsx/trunk/src/debugger/Probe.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/debugger/Probe.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -1,5 +1,8 @@ // $Id: $ +#ifndef PROBE_HH +#define PROBE_HH + #include "Subject.hh" #include "StringOp.hh" #include <string> @@ -66,3 +69,5 @@ } } // namespace openmsx + +#endif Added: openmsx/trunk/src/debugger/ProbeBreakPoint.cc =================================================================== --- openmsx/trunk/src/debugger/ProbeBreakPoint.cc (rev 0) +++ openmsx/trunk/src/debugger/ProbeBreakPoint.cc 2008-08-28 18:05:52 UTC (rev 8182) @@ -0,0 +1,51 @@ +// $Id$ + +#include "ProbeBreakPoint.hh" +#include "Probe.hh" +#include "Debugger.hh" +#include "TclObject.hh" + +namespace openmsx { + +unsigned ProbeBreakPoint::lastId = 0; + +ProbeBreakPoint::ProbeBreakPoint( + CliComm& cliComm, + std::auto_ptr<TclObject> command, + std::auto_ptr<TclObject> condition, + Debugger& debugger_, + ProbeBase& probe_) + : BreakPointBase(cliComm, command, condition) + , debugger(debugger_) + , probe(probe_) + , id(++lastId) +{ + probe.attach(*this); +} + +ProbeBreakPoint::~ProbeBreakPoint() +{ + probe.detach(*this); +} + +unsigned ProbeBreakPoint::getId() const +{ + return id; +} + +const ProbeBase& ProbeBreakPoint::getProbe() const +{ + return probe; +} + +void ProbeBreakPoint::update(const ProbeBase& /*subject*/) +{ + checkAndExecute(); +} + +void ProbeBreakPoint::subjectDeleted(const ProbeBase& /*subject*/) +{ + debugger.removeProbeBreakPoint(*this); +} + +} // namespace openmsx Added: openmsx/trunk/src/debugger/ProbeBreakPoint.hh =================================================================== --- openmsx/trunk/src/debugger/ProbeBreakPoint.hh (rev 0) +++ openmsx/trunk/src/debugger/ProbeBreakPoint.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -0,0 +1,42 @@ +// $Id$ + +#ifndef PROBEBREAKPOINT_HH +#define PROBEBREAKPOINT_HH + +#include "BreakPointBase.hh" +#include "Observer.hh" +#include <string> + +namespace openmsx { + +class Debugger; +class ProbeBase; + +class ProbeBreakPoint : public BreakPointBase, private Observer<ProbeBase> +{ +public: + ProbeBreakPoint(CliComm& CliComm, + std::auto_ptr<TclObject> command, + std::auto_ptr<TclObject> condition, + Debugger& debugger, + ProbeBase& probe); + ~ProbeBreakPoint(); + + unsigned getId() const; + const ProbeBase& getProbe() const; + +private: + // Observer<ProbeBase> + virtual void update(const ProbeBase& subject); + virtual void subjectDeleted(const ProbeBase& subject); + + Debugger& debugger; + ProbeBase& probe; + const unsigned id; + + static unsigned lastId; +}; + +} // namespace openmsx + +#endif Modified: openmsx/trunk/src/debugger/node.mk =================================================================== --- openmsx/trunk/src/debugger/node.mk 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/debugger/node.mk 2008-08-28 18:05:52 UTC (rev 8182) @@ -6,7 +6,7 @@ Debugger \ DasmTables \ SimpleDebuggable \ - Probe + Probe ProbeBreakPoint HDR_ONLY:= \ Debuggable Modified: openmsx/trunk/src/utils/Observer.hh =================================================================== --- openmsx/trunk/src/utils/Observer.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/utils/Observer.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -12,6 +12,7 @@ { public: virtual void update(const T& subject) = 0; + virtual void subjectDeleted(const T& subject) { /*nothing*/ } protected: virtual ~Observer() {} Modified: openmsx/trunk/src/utils/Subject.hh =================================================================== --- openmsx/trunk/src/utils/Subject.hh 2008-08-28 18:01:53 UTC (rev 8181) +++ openmsx/trunk/src/utils/Subject.hh 2008-08-28 18:05:52 UTC (rev 8182) @@ -43,6 +43,11 @@ template <typename T> Subject<T>::~Subject() { assert(!notifyInProgress); + Observers copy(observers); + for (typename Observers::const_iterator it = copy.begin(); + it != copy.end(); ++it) { + (*it)->subjectDeleted(*static_cast<const T*>(this)); + } assert(observers.empty()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |