From 3fa6f4b4c400c7354e05ac7bae128d4d9ee30e5c Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Mon, 14 Oct 2013 15:00:12 -0700 Subject: Add infrastructure for debug pretty printers --- Makefile.in | 2 ++ configure | 11 +++++++++ deps/attoconf | 2 +- real.make | 65 +++++++++++++++++++++++++++++++++++++------------- src/main-gdb-head.py | 59 +++++++++++++++++++++++++++++++++++++++++++++ src/main-gdb-tail.py | 2 ++ src/strings/zstring.py | 18 ++++++++++++++ 7 files changed, 142 insertions(+), 17 deletions(-) create mode 100644 src/main-gdb-head.py create mode 100644 src/main-gdb-tail.py create mode 100644 src/strings/zstring.py diff --git a/Makefile.in b/Makefile.in index 77c9873..1030212 100644 --- a/Makefile.in +++ b/Makefile.in @@ -27,6 +27,7 @@ HTMLDIR = @HTMLDIR@ DVIDIR = @DVIDIR@ PDFDIR = @PDFDIR@ PSDIR = @PSDIR@ +DEBUGDIR = @DEBUGDIR@ BISON = @BISON@ @@ -43,6 +44,7 @@ ENABLE_WARNINGS = @ENABLE_WARNINGS@ ENABLE_ABI6 = @ENABLE_ABI6@ ENABLE_CYGWIN_HACKS = @ENABLE_CYGWIN_HACKS@ ENABLE_COMPAT_SYMLINKS = @ENABLE_COMPAT_SYMLINKS@ +ENABLE_DEBUG = @ENABLE_DEBUG@ diff --git a/configure b/configure index 584f965..838cb34 100755 --- a/configure +++ b/configure @@ -55,6 +55,14 @@ class Configuration(Cxx, Flex, Bison, Install, ConfigHash, Templates): self.add_alias('--dev', ['--user', '--enable-warnings', '--enable-abi6'], help=None, hidden=False) + def paths(self): + super(Configuration, self).paths() + + self.add_option('--debugdir', init='/', + type=filepath, check=lambda build, DIR: None, + help='root for split debug files (often /usr/lib/debug)', hidden=False, + help_var='DIR') + def features(self): super(Configuration, self).features() # TODO: check VERSION_CONTROL environment variable? @@ -75,6 +83,9 @@ class Configuration(Cxx, Flex, Bison, Install, ConfigHash, Templates): self.add_bool_feature('compat-symlinks', init='yes', check=lambda build, ENABLE_COMPAT_SYMLINKS: None, help='Install symlinks to avoid breaking old scripts') + self.add_bool_feature('debug', init='yes', + check=lambda build, ENABLE_DEBUG: None, + help='Install extra files useful for debugging') def vars(self): super(Configuration, self).vars() diff --git a/deps/attoconf b/deps/attoconf index 2c30aa6..0f0e630 160000 --- a/deps/attoconf +++ b/deps/attoconf @@ -1 +1 @@ -Subproject commit 2c30aa6572b9c8e455fb0aba5b5ed75361962d6b +Subproject commit 0f0e6300534b8b847f139c04b9e6ed1cc1100d90 diff --git a/real.make b/real.make index e8442fe..acf656e 100644 --- a/real.make +++ b/real.make @@ -273,6 +273,10 @@ include ${DEPENDS} bin/%: $(MKDIR_FIRST) ${CXX} ${LDFLAGS} $^ ${LDLIBS} -o $@ + cat ${SRC_DIR}/src/main-gdb-head.py \ + $(wildcard $(patsubst obj/%.o,${SRC_DIR}/src/%.py,$^)) \ + ${SRC_DIR}/src/main-gdb-tail.py \ + > $@-gdb.py ${TEST_BINARIES}: obj/gtest-all.o @@ -287,26 +291,46 @@ test: $(patsubst bin/%,.run-%,${TEST_BINARIES}) .run-%: bin/% $< +install := install --backup=${ENABLE_BACKUPS_DURING_INSTALL} +install_exe := ${install} +install_dir := ${install} -d +install_data := ${install} -m 0644 +install_symlink := ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf + install: - install -d ${DESTDIR}${BINDIR} - install --backup=${ENABLE_BACKUPS_DURING_INSTALL} -t ${DESTDIR}${BINDIR} \ - $(wildcard ${BINARIES}) -# Is wildcard really the right thing to do? ^ -# cases to consider: -# all binaries built -# all binaries present, but some outdated. This is hard unless I dep. -# some binaries built -# no binaries built + @echo = Done installing + +install: install-bin +install-bin: + @echo + Installing binaries + ${install_dir} ${DESTDIR}${BINDIR} + ${install_exe} -t ${DESTDIR}${BINDIR} \ + ${BINARIES} +install-bin: install-bin-compat +install-bin-compat: ifeq (${ENABLE_COMPAT_SYMLINKS},yes) - @echo Installing compatibility symlinks - ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf tmwa-login ${DESTDIR}${BINDIR}/login-server - ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf tmwa-char ${DESTDIR}${BINDIR}/char-server - ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf tmwa-map ${DESTDIR}${BINDIR}/map-server - ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf tmwa-admin ${DESTDIR}${BINDIR}/ladmin - ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf tmwa-monitor ${DESTDIR}${BINDIR}/eathena-monitor + @echo + Installing compatibility symlinks + ${install_dir} ${DESTDIR}${BINDIR} + ${install_symlink} tmwa-login ${DESTDIR}${BINDIR}/login-server + ${install_symlink} tmwa-char ${DESTDIR}${BINDIR}/char-server + ${install_symlink} tmwa-map ${DESTDIR}${BINDIR}/map-server + ${install_symlink} tmwa-admin ${DESTDIR}${BINDIR}/ladmin + ${install_symlink} tmwa-monitor ${DESTDIR}${BINDIR}/eathena-monitor else - @echo Not installing compatibility symlinks + @echo - Not installing compatibility symlinks endif + +install: install-debug +install-debug: +ifeq (${ENABLE_DEBUG},yes) + @echo + Installing debug files + ${install_dir} ${DESTDIR}${DEBUGDIR}${BINDIR} + ${install_data} -t ${DESTDIR}${DEBUGDIR}${BINDIR} \ + $(patsubst %,%-gdb.py,${BINARIES}) +else + @echo - Not installing debug files +endif + tags: ${SOURCES} ${HEADERS} ctags --totals --c-kinds=+px -f $@ $^ @@ -326,6 +350,15 @@ conf-raw/int-%.h: FORCE echo "#define $* \\"; \ echo '$(value $*)'; \ } > $@ +bool_yes := true +bool_no := false +conf-raw/bool-%.h: FORCE + $(MKDIR_FIRST) + @grep -s -q '^$(bool_$(value $*))$$' $@ \ + || { \ + echo "#define $* \\"; \ + echo '$(bool_$(value $*))'; \ + } > $@ conf-raw/str-%.h: FORCE $(MKDIR_FIRST) @grep -s -q '^"$(value $*)"$$' $@ \ diff --git a/src/main-gdb-head.py b/src/main-gdb-head.py new file mode 100644 index 0000000..cfdce2b --- /dev/null +++ b/src/main-gdb-head.py @@ -0,0 +1,59 @@ +# Work around awkwardness in gdb's python printers: +# 1. In src/main-gdb-head.py, define the printer mechanism. +# 2. In src/*/*.py, define all the printer classes. +# 3. In src/main-gdb-tail.py, reflect to actually add the printers. + +# gdb sticks everything in one scope. +# This lets us enumerate what *we* added. +initial_globals = set(globals()) + +def finish(): + diff = set(globals()) - initial_globals + fp = FastPrinters() + # After this, don't access any more globals in this function. + global finish, initial_globals, FastPrinters + del finish, initial_globals, FastPrinters + + for k in diff: + v = globals()[k] + if hasattr(v, 'children') or hasattr(v, 'to_string'): + fp.add_printer(v) + + gdb.current_objfile().pretty_printers.append(fp) + +class FastPrinters(object): + ''' printer dispatch the way gdb *should* have done it + ''' + __slots__ = ('name', 'enabled', 'printers') + + def __init__(self): + self.name = 'tmwa' + self.enabled = True + self.printers = {} + + def add_printer(self, cls): + assert hasattr(cls, 'enabled') + self.printers[cls.name] = cls + + @property + def subprinters(self): + return self.printers.values() + + def strip_templates(self, name, __pattern=re.compile('<[^<>]>')): + # TODO what about '<' and '>' as non-type template parameters? + changed = 1 + while changed: + name, changed = __pattern.subn('', name) + return name + + def __call__(self, value): + stype = gdb.types.get_basic_type(value.type).tag + #dtype = gdb.types.get_basic_type(value.dynamic_type).tag + if stype is None: + return + + stype = self.strip_templates(stype) + p = self.printers.get(stype) + if p is not None and p.enabled: + return p(value) + return None diff --git a/src/main-gdb-tail.py b/src/main-gdb-tail.py new file mode 100644 index 0000000..241444f --- /dev/null +++ b/src/main-gdb-tail.py @@ -0,0 +1,2 @@ +# call the function defined in src/gdb-main-head.py +finish() diff --git a/src/strings/zstring.py b/src/strings/zstring.py new file mode 100644 index 0000000..5021e1c --- /dev/null +++ b/src/strings/zstring.py @@ -0,0 +1,18 @@ +class ZString(object): + ''' print a ZString + ''' + __slots__ = ('_value') + name = 'strings::ZString' + enabled = True + + def __init__(self, value): + self._value = value + + def children(self): + yield 'base', self._value['_base'] + + def to_string(self): + b = self._value['_b']['_ptr'] + e = self._value['_e']['_ptr'] + d = e - b + return b.lazy_string(length=d) -- cgit v1.2.3-60-g2f50