From eff9f165f3987e8a16022ac5165e5a15248824c0 Mon Sep 17 00:00:00 2001 From: cloud Date: Wed, 5 Apr 2017 18:37:14 -0500 Subject: [PATCH] Add ability to load individual symbols (#208) * add func to compile and load symbols from a file * break out add_symbol_file, fix ext splitting * Looks like for 2.7, file.flush invokes the native routine file_flush which invokes fflush. file.close invokes the native routine file_close --> close_the_file --> PyFileObject->f_close --> close(2). There is no call to any flush routine. file.__exit__ just invokes the close method on the file object. According to StackOverflow, file.close() implies file.flush(), but I don't see any code for it in the cpython source. Separately, flush() does not guarantee that the data is actually on disk. That requires calling fsync() or using O_SYNC. So it appears that the call to f.flush() is both unnecessary and incorrect. * We still need to call fsync to actually ensure the data hits the disk. However, the file descriptor is closed outside of the with block, and we can't guarantee the buffers are flushed in the with block without .flush(). --- pwndbg/typeinfo.py | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/pwndbg/typeinfo.py b/pwndbg/typeinfo.py index 3c669854d..e90a8aa2c 100644 --- a/pwndbg/typeinfo.py +++ b/pwndbg/typeinfo.py @@ -87,6 +87,7 @@ blacklist = ['regexp.h', 'xf86drm.h', 'libxl_json.h', 'xf86drmMode.h', 'libunwind.h','libmjollnir-objects.h','libunwind-coredump.h','libunwind-dynamic.h'] def load(name): + """Load symbol by name from headers in standard system include directory""" try: return gdb.lookup_type(name) except gdb.error: @@ -119,18 +120,37 @@ def load(name): {name} foo; '''.format(**locals()) - filename = '%s/%s_%s' % (tempdir, arch, '-'.join(name.split())) + filename = '%s/%s_%s.cc' % (tempdir, arch, '-'.join(name.split())) - if not os.path.exists(filename + '.o'): - with open(filename + '.cc', 'w+') as f: - f.write(source) - f.flush() + with open(filename, 'w+') as f: + f.write(source) + f.flush() + os.fsync(f.fileno()) + compile(filename) + + return gdb.lookup_type(name) + +def compile(filename=None, address=0): + """Compile and extract symbols from specified file""" + if filename is None: + print("Specify a filename to compile.") + return + + objectname = os.path.splitext(filename)[0] + ".o" + + if not os.path.exists(objectname): gcc = pwndbg.gcc.which() - gcc += ['-w','-c','-g',filename + '.cc','-o',filename + '.o'] + gcc += ['-w', '-c', '-g', filename, '-o', objectname] subprocess.check_output(' '.join(gcc), shell=True) - with pwndbg.events.Pause(): - gdb.execute('add-symbol-file %s.o 0' % filename, from_tty=False, to_string=True) + add_symbol_file(objectname, address) - return gdb.lookup_type(name) +def add_symbol_file(filename=None, address=0): + """Read additional symbol table information from the object file filename""" + if filename is None: + print("Specify a symbol file to add.") + return + + with pwndbg.events.Pause(): + gdb.execute('add-symbol-file %s %s' % (filename, address), from_tty=False, to_string=True)