# $Id$
CFLAGS = -Igensrc -ggdb
+CXXFLAGS = -Igensrc -ggdb
-all: glwrap.so gldump
+PACKAGES_gldbg = mspcore mspstrings mspio mspfs
+CXXFLAGS_gldbg = $(shell pkg-config --cflags $(PACKAGES_gldbg))
+LIBS_gldbg = $(shell pkg-config --libs $(PACKAGES_gldbg))
+
+all: glwrap.so gldump gldbg
glwrap.so: source/glwrap.o
$(CC) -shared -o $@ $^ $(LIBS) $(LDFLAGS)
gldump: source/gldecoder.o source/gldump.o source/glprint.o
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
+gldbg: source/gldbg.o source/gldecoder.o source/glprint.o
+ $(CXX) -o $@ $^ $(LIBS_gldbg) $(LIBS) $(LDFLAGS)
+
source/glwrap.o: source/functions.h gensrc/functions.enum gensrc/glwrap.funcs
source/gldecoder.o: source/functions.h gensrc/gldecoder.struct gensrc/gldecoder.funcs gensrc/gldecoder.funcs
source/gldump.o: source/gldecoder.h gensrc/gldecoder.struct source/glprint.h
source/glprint.o: gensrc/glprint.funcs gensrc/gldecoder.struct
+source/gldbg.o: source/gldbg.cpp source/gldbg.h source/gldecoder.h source/glprint.h
+ $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $<
+
gensrc/functions.enum gensrc/gldecoder.funcs gensrc/gldecoder.struct gensrc/glwrap.funcs gensrc/glprint.funcs: gensrc/.created genwrap.py gl.spec gl.tm
python ./genwrap.py
--- /dev/null
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <msp/core/except.h>
+#include <msp/fs/dir.h>
+#include <msp/io/print.h>
+#include <msp/strings/lexicalcast.h>
+#include "gldbg.h"
+#include "glprint.h"
+
+using namespace std;
+using namespace Msp;
+
+Application::RegApp<GlDbg> GlDbg::reg;
+
+GlDbg::GlDbg(int argc, char **argv):
+ pid(0),
+ sock_fd(-1),
+ glprint(glprint_new(0, 16384))
+{
+ libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
+ args.assign(argv+1, argv+argc);
+}
+
+int GlDbg::main()
+{
+ catch_signal(SIGINT);
+ launch();
+
+ Application::main();
+}
+
+void GlDbg::tick()
+{
+ int status;
+ int ret = waitpid(pid, &status, WNOHANG);
+ if(ret==pid)
+ {
+ if(WIFEXITED(status) || WIFSIGNALED(status))
+ {
+ IO::print("Target process exited\n");
+ exit(0);
+ }
+ }
+
+ pollfd pfd = { sock_fd, POLLIN, 0 };
+ ret = poll(&pfd, 1, -1);
+ if(ret>0)
+ {
+ char rbuf[1024];
+ ret = read(sock_fd, rbuf, 1024);
+ if(ret>0)
+ {
+ buffer.append(rbuf, ret);
+ while(buffer.size()>buf_offset)
+ {
+ int ret = gldecoder_decode(glprint, buffer.data()+buf_offset, buffer.size()-buf_offset);
+ if(ret<0)
+ break;
+ buf_offset += ret;
+ IO::print("%s\n", glprint_get_buffer(glprint));
+ }
+ if(buf_offset>8192)
+ {
+ buffer.erase(0, buf_offset);
+ buf_offset=0;
+ }
+ }
+ }
+}
+
+void GlDbg::launch()
+{
+ int fds[2];
+ socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+ sock_fd = fds[0];
+
+ pid = fork();
+ if(pid==0)
+ {
+ string fd_str = lexical_cast(fds[1]);
+ setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str(), true);
+ setenv("GLWRAP_FD", fd_str.c_str(), true);
+ close(fds[0]);
+ std::vector<char *> argv(args.size()+1);
+ for(unsigned i=0; i<args.size(); ++i)
+ argv[i] = strdup(args[i].c_str());
+ argv[args.size()] = 0;
+ execvp(argv[0], &argv[0]);
+ ::exit(127);
+ }
+ else if(pid>0)
+ {
+ close(fds[1]);
+ }
+ else
+ {
+ throw SystemError("Could not launch process", errno);
+ }
+}
--- /dev/null
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#ifndef GLDBG_H_
+#define GLDBG_H_
+
+#include <string>
+#include <vector>
+#include <msp/core/application.h>
+#include <msp/fs/path.h>
+#include "glstate.h"
+
+class GlDbg: public Msp::Application
+{
+private:
+ Msp::FS::Path libdir;
+ int pid;
+ std::vector<std::string> args;
+ int sock_fd;
+ std::string buffer;
+ unsigned buf_offset;
+ GlDecoder *glprint;
+
+ static RegApp<GlDbg> reg;
+
+public:
+ GlDbg(int, char **);
+ int main();
+private:
+ void tick();
+ void launch();
+};
+
+#endif