]> git.tdb.fi Git - gldbg.git/commitdiff
Track owners of breakpoints
authorMikko Rasa <tdb@tdb.fi>
Wed, 12 Jan 2011 11:59:07 +0000 (11:59 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 12 Jan 2011 11:59:07 +0000 (11:59 +0000)
Send breakpoint flag from glwrap.so
Delay announcing stop until the stream has been flushed
Let tools know about process starting and stopping
Add methods for hold and sending arbitary packets to GlDbg
Break on any tracepoint if holding
Link glwrap.so against dl.so

Makefile
source/commandinterpreter.cpp
source/gldbg.cpp
source/gldbg.h
source/gldecoder.c
source/gldecoder.struct.t
source/glwrap.c
source/tool.h

index 6313e0fb8477387beb171fcb9461b274473d722a..010fe2851ec37281753482d8d565ccd0cc001240 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -71,6 +71,7 @@ $(OBJECTS_gldbg): CXXFLAGS += $(shell pkg-config --cflags $(PACKAGES_gldbg))
 gldbg: LIBS += $(shell pkg-config --libs $(PACKAGES_gldbg)) -lreadline
 gldump gldbg: LIBS += ./libgldbg.a
 glwrap.so: LDFLAGS += -s
+glwrap.so: LIBS += -ldl
 
 glwrap.so: $(OBJECTS_glwrap) glwrap.ld
        $(CC) -shared -o $@ $^ $(LIBS) $(LDFLAGS)
index 25f004ef32a639497437eaf5709c0b87c64465d5..fe0c3f1bc5df51334de7b2c00233c659d05fb511 100644 (file)
@@ -119,7 +119,7 @@ void CommandInterpreter::cmd_break(const string &args)
        if(!func)
                throw InvalidParameterValue("Unknown function");
 
-       gldbg.set_breakpoint(func, BREAK_CALL);
+       gldbg.set_breakpoint(func, BREAK_CALL, 0);
 }
 
 void CommandInterpreter::cmd_unbreak(const string &args)
@@ -128,18 +128,18 @@ void CommandInterpreter::cmd_unbreak(const string &args)
        if(!func)
                throw InvalidParameterValue("Unknown function");
 
-       gldbg.clear_breakpoint(func, BREAK_CALL);
+       gldbg.clear_breakpoint(func, BREAK_CALL, 0);
 }
 
 void CommandInterpreter::cmd_next(const string &)
 {
-       gldbg.set_breakpoint(0, BREAK_CALL);
+       gldbg.set_breakpoint(0, BREAK_CALL, 0);
        gldbg.get_process().resume();
 }
 
 void CommandInterpreter::cmd_finish(const string &)
 {
-       gldbg.set_breakpoint(0, BREAK_RETURN);
+       gldbg.set_breakpoint(0, BREAK_RETURN, 0);
        gldbg.get_process().resume();
 }
 
index 43827378f4faed462e35efe2be4b3a2ca2dfffcb..001742d39599b85942702f797d8e8ed383d7a16d 100644 (file)
@@ -5,6 +5,7 @@ Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
+#include <algorithm>
 #include <cstdlib>
 #include <fcntl.h>
 #include <signal.h>
@@ -31,7 +32,9 @@ GlDbg::GlDbg(int argc, char **argv):
        process(vector<string>(argv+1, argv+argc)),
        buf_offset(0),
        flushing(false),
-       got_sigchld(false)
+       got_sigchld(false),
+       stop_reason(0),
+       current_break(0)
 {
        FS::Path libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
        process.setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str());
@@ -43,7 +46,7 @@ GlDbg::GlDbg(int argc, char **argv):
 
 GlDbg::~GlDbg()
 {
-       for(list<Tool *>::iterator i=tools.begin(); i!=tools.end(); ++i)
+       for(ToolList::iterator i=tools.begin(); i!=tools.end(); ++i)
                delete *i;
 }
 
@@ -78,24 +81,83 @@ void GlDbg::launch()
        process.setenv("GLWRAP_CTRL_FD", lexical_cast(fds[1]));
        process.launch();
        close(fds[1]);
+
+       breakpoints.clear();
+       for(ToolList::iterator i=tools.begin(); i!=tools.end(); ++i)
+               (*i)->process_started();
 }
 
-void GlDbg::set_breakpoint(unsigned short func, char flag)
+void GlDbg::send(GlPacket *pkt)
 {
-       GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
-       packet_write_short(pkt, func);
-       packet_write_char(pkt, flag);
-       packet_write_char(pkt, 0);
        packet_send(pkt, sock_fd);
 }
 
-void GlDbg::clear_breakpoint(unsigned short func, char flag)
+void GlDbg::hold()
 {
-       GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
-       packet_write_short(pkt, func);
-       packet_write_char(pkt, 0);
-       packet_write_char(pkt, flag);
-       packet_send(pkt, sock_fd);
+       GlPacket *pkt = packet_begin(FUNC_GLDHOLD);
+       send(pkt);
+}
+
+void GlDbg::set_breakpoint(unsigned short func, unsigned char flag, Tool *owner)
+{
+       Breakpoint *bp = (func ? get_breakpoint(func, flag) : 0);
+       if(bp)
+               bp->add_owner(owner);
+       else
+       {
+               if(func)
+               {
+                       breakpoints.push_back(Breakpoint(func, flag));
+                       breakpoints.back().add_owner(owner);
+               }
+
+               GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
+               packet_write_short(pkt, func);
+               packet_write_char(pkt, flag);
+               packet_write_char(pkt, 0);
+               send(pkt);
+       }
+}
+
+void GlDbg::clear_breakpoint(unsigned short func, unsigned char flag, Tool *owner)
+{
+       Breakpoint *bp = get_breakpoint(func, flag);
+       if(bp)
+       {
+               bp->remove_owner(owner);
+               if(bp->owners.empty())
+               {
+                       if(current_break==bp)
+                               current_break = 0;
+
+                       // XXX Inefficient.  Should get_breakpoint() return an iterator?
+                       for(BreakList::iterator i=breakpoints.begin(); i!=breakpoints.end(); ++i)
+                               if(i->function==func && i->flag==flag)
+                               {
+                                       breakpoints.erase(i);
+                                       break;
+                               }
+
+                       GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
+                       packet_write_short(pkt, func);
+                       packet_write_char(pkt, 0);
+                       packet_write_char(pkt, flag);
+                       send(pkt);
+               }
+       }
+}
+
+void GlDbg::resume_from_break(Tool *tool)
+{
+       if(!current_break)
+               return;
+
+       ToolList::iterator i = find(break_holders.begin(), break_holders.end(), tool);
+       if(i!=break_holders.end())
+               break_holders.erase(i);
+
+       if(break_holders.empty())
+               process.resume();
 }
 
 void GlDbg::quit(bool force)
@@ -110,18 +172,9 @@ void GlDbg::tick()
        if(got_sigchld)
        {
                got_sigchld = false;
-               int ret = process.check();
-               if(ret==0x100)
-                       IO::print("Target process exited normally\n");
-               else if((ret>>8)==1)
-                       IO::print("Target process exited with status %d\n", ret&0xFF);
-               else if((ret>>8)==2)
-                       IO::print("Target process terminated with signal %d\n", ret&0xFF);
-               else if((ret>>8)==3)
-               {
-                       IO::print("Target process stopped by signal %d\n", ret&0xFF);
+               stop_reason = process.check();
+               if((stop_reason>>8)==3)
                        flushing = true;
-               }
        }
 
        Process::State pstate = process.get_state();
@@ -129,6 +182,20 @@ void GlDbg::tick()
                read_stream();
        else
        {
+               if(stop_reason)
+               {
+                       if(stop_reason==0x100)
+                               IO::print("Target process exited normally\n");
+                       else if((stop_reason>>8)==1)
+                               IO::print("Target process exited with status %d\n", stop_reason&0xFF);
+                       else if((stop_reason>>8)==2)
+                               IO::print("Target process terminated with signal %d\n", stop_reason&0xFF);
+                       else if((stop_reason>>8)==3)
+                               IO::print("Target process stopped by signal %d\n", stop_reason&0xFF);
+
+                       stop_reason = 0;
+               }
+
                char *line = readline("gldbg> ");
                if(line)
                {
@@ -171,10 +238,22 @@ void GlDbg::read_stream()
                                if(func==FUNC_GLDBREAK)
                                {
                                        packet_read_short(pkt, (short *)&func);
-                                       IO::print("Breakpoint: %s\n", get_function_name(func));
+                                       unsigned char flag;
+                                       packet_read_char(pkt, (char *)&flag);
+
+                                       current_break = get_breakpoint(func, flag);
+                                       bool announce = !current_break;
+                                       if(current_break)
+                                       {
+                                               break_holders = current_break->owners;
+                                               announce = current_break->has_owner(0);
+                                       }
+
+                                       if(announce)
+                                               IO::print("Breakpoint: %s\n", get_function_name(func));
                                }
 
-                               for(list<Tool *>::iterator i=tools.begin(); i!=tools.end(); ++i)
+                               for(ToolList::iterator i=tools.begin(); i!=tools.end(); ++i)
                                        (*i)->decode(data, len);
                                buf_offset += len;
                        }
@@ -186,7 +265,27 @@ void GlDbg::read_stream()
                }
        }
        else if(flushing)
+       {
                flushing = false;
+
+               if(stop_reason)
+               {
+                       for(ToolList::iterator i=tools.begin(); i!=tools.end(); ++i)
+                               (*i)->process_stopped(stop_reason);
+
+                       if(process.get_state()==Process::RUNNING)
+                               current_break = 0;
+               }
+       }
+}
+
+GlDbg::Breakpoint *GlDbg::get_breakpoint(unsigned short func, unsigned char flag)
+{
+       for(BreakList::iterator i=breakpoints.begin(); i!=breakpoints.end(); ++i)
+               if(i->function==func && i->flag==flag)
+                       return &*i;
+
+       return 0;
 }
 
 void GlDbg::sighandler(int sig)
@@ -194,3 +293,29 @@ void GlDbg::sighandler(int sig)
        if(sig==SIGCHLD)
                got_sigchld = true;
 }
+
+
+GlDbg::Breakpoint::Breakpoint(unsigned short f, unsigned char l):
+       function(f),
+       flag(l)
+{ }
+
+void GlDbg::Breakpoint::add_owner(Tool *t)
+{
+       ToolList::iterator i = find(owners.begin(), owners.end(), t);
+       if(i==owners.end())
+               owners.push_back(t);
+}
+
+bool GlDbg::Breakpoint::has_owner(Tool *t) const
+{
+       ToolList::const_iterator i = find(owners.begin(), owners.end(), t);
+       return i!=owners.end();
+}
+
+void GlDbg::Breakpoint::remove_owner(Tool *t)
+{
+       ToolList::iterator i = find(owners.begin(), owners.end(), t);
+       if(i!=owners.end())
+               owners.erase(i);
+}
index da5664eddf749102f4a996bdab12e14f35983fdc..99f0863c2c3f72cf91852ea0e356781aed23994c 100644 (file)
@@ -13,6 +13,7 @@ Distributed under the GPL
 #include <msp/core/application.h>
 #include <msp/fs/path.h>
 #include "commandinterpreter.h"
+#include "packet.h"
 #include "process.h"
 
 class Tool;
@@ -20,14 +21,35 @@ class Tool;
 class GlDbg: public Msp::Application
 {
 private:
+       typedef std::list<Tool *> ToolList;
+
+       struct Breakpoint
+       {
+               unsigned short function;
+               unsigned char flag;
+               ToolList owners;
+
+               Breakpoint(unsigned short, unsigned char);
+
+               void add_owner(Tool *);
+               bool has_owner(Tool *) const;
+               void remove_owner(Tool *);
+       };
+
+       typedef std::list<Breakpoint> BreakList;
+
        CommandInterpreter cmd_interp;
        Process process;
        int sock_fd;
        std::string buffer;
        unsigned buf_offset;
        bool flushing;
-       std::list<Tool *> tools;
+       ToolList tools;
        bool got_sigchld;
+       int stop_reason;
+       BreakList breakpoints;
+       const Breakpoint *current_break;
+       ToolList break_holders;
 
        static RegApp<GlDbg> reg;
 
@@ -39,13 +61,17 @@ public:
        CommandInterpreter &get_command_interpreter() { return cmd_interp; }
        Process &get_process() { return process; }
        void launch();
-       void set_breakpoint(unsigned short, char);
-       void clear_breakpoint(unsigned short, char);
+       void send(GlPacket *);
+       void hold();
+       void set_breakpoint(unsigned short, unsigned char, Tool *);
+       void clear_breakpoint(unsigned short, unsigned char, Tool *);
+       void resume_from_break(Tool *);
        void quit(bool);
 private:
        void tick();
        void check_child();
        void read_stream();
+       Breakpoint *get_breakpoint(unsigned short, unsigned char);
        virtual void sighandler(int);
 };
 
index 81b1a43c128b8f3ddba292f86cc883dff2c9ff17..22b6285a244130fae4dd8d7af9481433402e7741 100644 (file)
@@ -74,9 +74,11 @@ static void decode_gldError(GlDecoder *dec, GlPacket *pkt)
 static void decode_gldBreak(GlDecoder *dec, GlPacket *pkt)
 {
        unsigned short func;
+       unsigned char flag;
        packet_read_short(pkt, (short *)&func);
+       packet_read_char(pkt, (char *)&flag);
        if(dec->gldBreak)
-               dec->gldBreak(dec->user_data, func);
+               dec->gldBreak(dec->user_data, func, flag);
        else if(dec->unhandled)
                dec->unhandled(dec->user_data, FUNC_GLDBREAK);
 }
index cc146ccec71a817edc3aa5eb4fd687f911e66361..ac0e098664ab0a8ea1cf60178cd814376c65909a 100644 (file)
@@ -10,6 +10,6 @@ for p in params:
        w(', %s', p.ctype)
 wl(');')
 :      void (*gldError)(void *, GLenum);
-:      void (*gldBreak)(void *, unsigned short);
+:      void (*gldBreak)(void *, unsigned short, unsigned char);
 :      void (*unhandled)(void *, unsigned short);
 :} GlDecoder;
index c70b308384b339888dc4ab4527fc7a86df4fa4dc..c121e22709c819eb3e9040245818e419023bd49e 100644 (file)
@@ -171,15 +171,22 @@ static void receive(void)
 
 void tracepoint(unsigned short func, int flag)
 {
+       int breakpoint;
+
        receive();
 
-       if((breakpoints[func]|break_any)&flag)
+       breakpoint = (breakpoints[func]|break_any)&flag;
+       if(breakpoint || hold)
        {
                GlPacket *pkt;
 
-               pkt = packet_begin(FUNC_GLDBREAK);
-               packet_write_short(pkt, func);
-               packet_send(pkt, get_out_fd());
+               if(breakpoint)
+               {
+                       pkt = packet_begin(FUNC_GLDBREAK);
+                       packet_write_short(pkt, func);
+                       packet_write_char(pkt, flag);
+                       packet_send(pkt, get_out_fd());
+               }
 
                break_any = 0;
 
index 0d234d2caf9c47e196096777635602913f80d496..29f9ca8c28fd6cb336713fc9d026e155f5e21321 100644 (file)
@@ -31,6 +31,8 @@ public:
        virtual ~Tool() { }
 
        virtual void decode(const char *, unsigned) = 0;
+       virtual void process_started() { }
+       virtual void process_stopped(int) { }
 
        static std::list<Factory *> &get_factories();
 };