3 This file is part of gldbg
4 Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
12 #include <sys/socket.h>
13 #include <readline/readline.h>
14 #include <msp/core/except.h>
15 #include <msp/fs/dir.h>
16 #include <msp/io/print.h>
17 #include <msp/strings/lexicalcast.h>
18 #include "functions.h"
20 #include "gldecoder.h"
27 Application::RegApp<GlDbg> GlDbg::reg;
29 GlDbg::GlDbg(int argc, char **argv):
31 process(vector<string>(argv+1, argv+argc)),
36 FS::Path libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
37 process.setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str());
39 const list<Tool::Factory *> &factories = Tool::get_factories();
40 for(list<Tool::Factory *>::const_iterator i=factories.begin(); i!=factories.end(); ++i)
41 tools.push_back((*i)->create(*this));
46 for(list<Tool *>::iterator i=tools.begin(); i!=tools.end(); ++i)
53 catch_signal(SIGCHLD);
54 set_loop_mode(TICK_BUSY);
56 IO::print("GLdbg 0.0\n");
57 IO::print("Copyright © 2009-2010 Mikkosoft Productions\n");
58 IO::print("Type \"help\" for a list of commands\n");
67 if(process.get_state()!=Process::INACTIVE)
68 throw InvalidState("Program is already running");
71 socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
74 int flags = fcntl(sock_fd, F_GETFD);
75 fcntl(sock_fd, F_SETFD, flags|FD_CLOEXEC);
77 process.setenv("GLWRAP_FD", lexical_cast(fds[1]));
78 process.setenv("GLWRAP_CTRL_FD", lexical_cast(fds[1]));
83 void GlDbg::set_breakpoint(unsigned short func, char flag)
85 GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
86 packet_write_short(pkt, func);
87 packet_write_char(pkt, flag);
88 packet_write_char(pkt, 0);
89 packet_send(pkt, sock_fd);
92 void GlDbg::clear_breakpoint(unsigned short func, char flag)
94 GlPacket *pkt = packet_begin(FUNC_GLDBREAK);
95 packet_write_short(pkt, func);
96 packet_write_char(pkt, 0);
97 packet_write_char(pkt, flag);
98 packet_send(pkt, sock_fd);
101 void GlDbg::quit(bool force)
103 if(!force && process.get_state()!=Process::INACTIVE)
104 throw InvalidState("Program is still running");
113 int ret = process.check();
115 IO::print("Target process exited normally\n");
117 IO::print("Target process exited with status %d\n", ret&0xFF);
119 IO::print("Target process terminated with signal %d\n", ret&0xFF);
122 IO::print("Target process stopped by signal %d\n", ret&0xFF);
127 Process::State pstate = process.get_state();
128 if((pstate!=Process::INACTIVE && pstate!=Process::STOPPED) || flushing)
132 char *line = readline("gldbg> ");
137 cmd_interp.execute(line);
139 catch(const Exception &e)
141 IO::print("%s\n", e.what());
145 else if(pstate==Process::INACTIVE)
150 void GlDbg::read_stream()
152 pollfd pfd = { sock_fd, POLLIN, 0 };
153 int ret = poll(&pfd, 1, (flushing ? 0 : -1));
157 ret = read(sock_fd, rbuf, 1024);
160 buffer.append(rbuf, ret);
161 while(buffer.size()>buf_offset)
163 const char *data = buffer.data()+buf_offset;
164 unsigned len = buffer.size()-buf_offset;
165 GlPacket *pkt = packet_receive_str(data, &len);
170 packet_read_short(pkt, (short *)&func);
171 if(func==FUNC_GLDBREAK)
173 packet_read_short(pkt, (short *)&func);
174 IO::print("Breakpoint: %s\n", get_function_name(func));
177 for(list<Tool *>::iterator i=tools.begin(); i!=tools.end(); ++i)
178 (*i)->decode(data, len);
183 buffer.erase(0, buf_offset);
192 void GlDbg::sighandler(int sig)