def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" sep = '' for objfile in gdb.objfiles(): if objfile.type_printers: print ("%sType printers for %s:" % (sep, objfile.filename)) self.list_type_printers(objfile.type_printers) sep = '\n' if gdb.current_progspace().type_printers: print ("%sType printers for program space:" % sep) self.list_type_printers(gdb.current_progspace().type_printers) sep = '\n' if gdb.type_printers: print ("%sGlobal type printers:" % sep) self.list_type_printers(gdb.type_printers)
def invoke(self, arg, from_tty): elf = gdb.current_progspace().filename samples = parse.sample_parser(parse.get_keyvals(elf), parse.get_tp_sections(elf), get_trace_buffer(), PTR_SIZE) for sample in samples: print(sample)
def r2pipe(): """ Spawn and return a r2pipe handle for the current process file. This function requires a radare2 installation plus the r2pipe python library. The base address is automatically set for PIE when loading the binary. After opening the handle, the binary is automatically analyzed. Raises ImportError if r2pipe python library is not available. Raises Exception if anything goes fatally wrong. Returns a r2pipe.open handle. """ filename = gdb.current_progspace().filename if not filename: raise Exception('Could not find objfile to create a r2pipe for') import r2pipe flags = ['-e', 'io.cache=true'] if pwndbg.elf.get_elf_info(filename).is_pie and pwndbg.elf.exe(): flags.extend(['-B', hex(pwndbg.elf.exe().address)]) r2 = r2pipe.open(filename, flags=flags) r2.cmd("aaaa") return r2
def decompile(func=None): """ Return the source of the given function decompiled by ghidra. If no function is given, decompile the function within the current pc. This function requires radare2, r2pipe and r2ghidra. Raises Exception if any fatal error occures. """ try: r2 = pwndbg.radare2.r2pipe() except ImportError: raise Exception('r2pipe not available, but required for r2->ghidra bridge') # LD -> list supported decompilers (e cmd.pdc=?) # Outputs for example: pdc\npdg if "pdg" not in r2.cmd("LD").split("\n"): raise Exception('radare2 plugin r2ghidra must be installed and available from r2') if not func: func = hex(pwndbg.regs[pwndbg.regs.current.pc]) if pwndbg.proc.alive else 'main' src = r2.cmdj("pdgj @" + func) if not src: raise Exception("Decompile command failed, check if '{}' is a valid target".format(func)) current_line_marker = '/*%%PWNDBG_CODE_MARKER%%*/' source = src.get("code", "") # If not running there is no current pc to mark if pwndbg.proc.alive: pc = pwndbg.regs[pwndbg.regs.current.pc] closest = 0 for off in (a.get("offset", 0) for a in src.get("annotations", [])): if abs(pc - closest) > abs(pc - off): closest = off pos_annotations = sorted([a for a in src.get("annotations", []) if a.get("offset") == closest], key=lambda a: a["start"]) # Append code prefix marker for the current line and replace it later if pos_annotations: curline = source.count("\n", 0, pos_annotations[0]["start"]) source = source.split("\n") line = source[curline] if line.startswith(' '): line = line[min(4, len(pwndbg.config.code_prefix) + 1):] source[curline] = current_line_marker + ' ' + line source = "\n".join(source) if pwndbg.config.syntax_highlight: # highlighting depends on the file extension to guess the language, so try to get one... src_filename = pwndbg.symbol.selected_frame_source_absolute_filename() if not src_filename: filename = gdb.current_progspace().filename src_filename = filename + ".c" if os.path.basename(filename).find(".") < 0 else filename source = H.syntax_highlight(source, src_filename) # Replace code prefix marker after syntax highlighting source = source.replace(current_line_marker, C.prefix(pwndbg.config.code_prefix), 1) return source
def _sort_list(): """ Internal Worker function to merge all known frame-filter lists, prune any filters with the state set to "disabled", and sort the list on the frame-filter's "priority" attribute. Returns: sorted_list: A sorted, pruned list of frame filters to execute. """ all_filters = [] for objfile in gdb.objfiles(): all_filters = all_filters + objfile.frame_filters.values() cp = gdb.current_progspace() all_filters = all_filters + cp.frame_filters.values() all_filters = all_filters + gdb.frame_filters.values() sorted_frame_filters = sorted(all_filters, key = get_priority, reverse = True) sorted_frame_filters = filter(get_enabled, sorted_frame_filters) return sorted_frame_filters
def context_ghidra(func=None, target=sys.stdout, with_banner=True, width=None, force_show=False): banner = [pwndbg.ui.banner("ghidra decompile", target=target, width=width)] if config_context_ghidra == "never" and not force_show: return [] elif config_context_ghidra == "if-no-source" and not force_show: try: with open(gdb.selected_frame().find_sal().symtab.fullname()) as _: pass except: # a lot can go wrong in search of source code. return [] # we don't care what, just that it did not work out well... filename = gdb.current_progspace().filename try: r2 = init_radare2(filename) # LD list supported decompilers (e cmd.pdc=?) # Outputs for example:: pdc\npdg if not "pdg" in r2.cmd("LD").split("\n"): return banner + ["radare2 plugin r2ghidra-dec must be installed and available from r2"] except ImportError: # no r2pipe present return banner + ["r2pipe not available, but required for r2->ghidra-bridge"] if func is None: try: func = hex(pwndbg.regs[pwndbg.regs.current.pc]) except: func = "main" src = r2.cmdj("pdgj @" + func) source = src.get("code", "") curline = None try: cur = pwndbg.regs[pwndbg.regs.current.pc] except AttributeError: cur = None # If not running there is no current.pc if cur is not None: closest = 0 for off in (a.get("offset", 0) for a in src.get("annotations", [])): if abs(cur - closest) > abs(cur - off): closest = off pos_annotations = sorted([a for a in src.get("annotations", []) if a.get("offset") == closest], key=lambda a: a["start"]) if pos_annotations: curline = source.count("\n", 0, pos_annotations[0]["start"]) source = source.split("\n") # Append --> for the current line if possible if curline is not None: line = source[curline] if line.startswith(' '): line = line[4:] source[curline] = '--> ' + line # Join the source for highlighting source = "\n".join(source) if pwndbg.config.syntax_highlight: # highlighting depends on the file extension to guess the language, so try to get one... try: # try to read the source filename from debug information src_filename = gdb.selected_frame().find_sal().symtab.fullname() except: # if non, take the original filename and maybe append .c (just assuming is was c) src_filename = filename+".c" if os.path.basename(filename).find(".") < 0 else filename source = H.syntax_highlight(source, src_filename) source = source.split("\n") return banner + source if with_banner else source
def do_enable_pretty_printer(arg, flag): """Internal worker for enabling/disabling pretty-printers.""" (object_re, name_re, subname_re) = parse_printer_regexps(arg) total = 0 if object_re.match("global"): total += do_enable_pretty_printer_1(gdb.pretty_printers, name_re, subname_re, flag) cp = gdb.current_progspace() if object_re.match("progspace"): total += do_enable_pretty_printer_1(cp.pretty_printers, name_re, subname_re, flag) for objfile in gdb.objfiles(): if object_re.match(objfile.filename): total += do_enable_pretty_printer_1(objfile.pretty_printers, name_re, subname_re, flag) if flag: state = "enabled" else: state = "disabled" print("%d %s %s" % (total, pluralize("printer", total), state)) # Print the total list of printers currently enabled/disabled. # This is to further assist the user in determining whether the result # is expected. Since we use regexps to select it's useful. show_pretty_printer_enabled_summary()
def debug_map_stop_handler(event): # Make sure we handle connecting to a new process correctly: # update the debug maps if we never did it before. if not isinstance(event, gdb.BreakpointEvent): progspace = gdb.current_progspace() if not hasattr(progspace, 'debug_maps'): gdb.execute('update-debug-maps')
def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" (object_re, name_re, subname_re) = parse_printer_regexps(arg) self.invoke1( "global pretty-printers:", gdb.pretty_printers, "global", object_re, name_re, subname_re, ) cp = gdb.current_progspace() self.invoke1( "progspace %s pretty-printers:" % cp.filename, cp.pretty_printers, "progspace", object_re, name_re, subname_re, ) for objfile in gdb.objfiles(): self.invoke1( "objfile %s pretty-printers:" % objfile.filename, objfile.pretty_printers, objfile.filename, object_re, name_re, subname_re, )
def complete(self, text, word): result = [] for objfile in gdb.objfiles(): self.add_some(result, word, objfile.type_printers) self.add_some(result, word, gdb.current_progspace().type_printers) self.add_some(result, word, gdb.type_printers) return result
def setup_breakpoints(self): self.elf = gdb.current_progspace().filename print "Searching symbol table for functions, this may take a while..." functions = get_c_function_names(self.elf) for (name, addr) in functions: EntryBreak(name, self) print "...done."
def do_enable_pretty_printer (arg, flag): """Internal worker for enabling/disabling pretty-printers.""" (object_re, name_re, subname_re) = parse_printer_regexps(arg) total = 0 if object_re.match("global"): total += do_enable_pretty_printer_1(gdb.pretty_printers, name_re, subname_re, flag) cp = gdb.current_progspace() if object_re.match("progspace"): total += do_enable_pretty_printer_1(cp.pretty_printers, name_re, subname_re, flag) for objfile in gdb.objfiles(): if object_re.match(objfile.filename): total += do_enable_pretty_printer_1(objfile.pretty_printers, name_re, subname_re, flag) if flag: state = "enabled" else: state = "disabled" print ("%d %s %s" % (total, pluralize("printer", total), state)) # Print the total list of printers currently enabled/disabled. # This is to further assist the user in determining whether the result # is expected. Since we use regexps to select it's useful. show_pretty_printer_enabled_summary()
def __init__(self): # set required attributes self.name = 'Rot13Filter' self.enabled = True self.priority = 0 # register with current program space gdb.current_progspace().frame_filters[self.name] = self
def main(): args = parseCommandLine() fileName = gdb.current_progspace().filename server = GDBserver(args.start_num, args.num_injections, args.board, args.source_dir, fileName) server.setPorts(args.gdb_port, args.python_port) server.setDebug(args.debug_commands) gdbHandlers.setServer(server) server.run()
def __reset_on_base(): filename = gdb.current_progspace().filename base = pwndbg.elf.exe().address if pwndbg.elf.exe() else None if reset_on_new_base_address.base != base or reset_on_new_base_address.filename != filename: reset_on_new_base_address.filename = filename reset_on_new_base_address.base = base for obj in reset_on_new_base_address.caches: obj.clear()
def return_list(name): """ Internal Worker function to return the frame filter dictionary, depending on the name supplied as an argument. If the name is not "all", "global" or "progspace", it is assumed to name an object-file. Arguments: name: The name of the list, as specified by GDB user commands. Returns: A dictionary object for a single specified dictionary, or a list containing all the items for "all" Raises: gdb.GdbError: A dictionary of that name cannot be found. """ # If all dictionaries are wanted in the case of "all" we # cannot return a combined dictionary as keys() may clash in # between different dictionaries. As we just want all the frame # filters to enable/disable them all, just return the combined # items() as a chained iterator of dictionary values. if name == "all": glob = gdb.frame_filters.values() prog = gdb.current_progspace().frame_filters.values() return_iter = itertools.chain(glob, prog) for objfile in gdb.objfiles(): return_iter = itertools.chain(return_iter, objfile.frame_filters.values()) return return_iter if name == "global": return gdb.frame_filters else: if name == "progspace": cp = gdb.current_progspace() return cp.frame_filters else: for objfile in gdb.objfiles(): if name == objfile.filename: return objfile.frame_filters msg = "Cannot find frame-filter dictionary for '" + name + "'" raise gdb.GdbError(msg)
def __init__(self): # set required attributes self.name = 'UserFilter' self.enabled = True self.priority = 0 # register with current program space # (manual suggests avoiding global filter list; this seems appropriate) gdb.current_progspace().frame_filters[self.name] = self
def set_xm_status(arg, status): """Set the status (enabled/disabled) of xmethods matching ARG. This is a helper function for enable/disable commands. ARG is the argument string passed to the commands. """ locus_re, matcher_re, name_re = parse_xm_command_args(arg) set_xm_status1(get_global_method_matchers(locus_re, matcher_re), name_re, status) set_xm_status1(get_method_matchers_in_loci([gdb.current_progspace()], locus_re, matcher_re), name_re, status) set_xm_status1(get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), name_re, status)
def gdb_address_to_function(address): try: block = gdb.current_progspace().block_for_pc(address) while block is not None: if block.function: return str(block.function) block = block.superblock except RuntimeError: pass return hex(address)
def invoke(self, arg, from_tty): locus_re, matcher_re, name_re = parse_xm_command_args(arg) print_xm_info(get_global_method_matchers(locus_re, matcher_re), name_re) print_xm_info( get_method_matchers_in_loci([gdb.current_progspace()], locus_re, matcher_re), name_re) print_xm_info( get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), name_re)
def invoke(self, arg, from_tty): self.print_list("global frame-filters:", gdb.frame_filters, True) cp = gdb.current_progspace() self.print_list("progspace %s frame-filters:" % cp.filename, cp.frame_filters, True) for objfile in gdb.objfiles(): self.print_list("objfile %s frame-filters:" % objfile.filename, objfile.frame_filters, False)
def invoke(self, arg, from_tty): locus_re, matcher_re, name_re = parse_xm_command_args(arg) print_xm_info(get_global_method_matchers(locus_re, matcher_re), name_re) print_xm_info( get_method_matchers_in_loci( [gdb.current_progspace()], locus_re, matcher_re), name_re) print_xm_info( get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), name_re)
def invoke(self, arg, from_tty): locus_re, name_re = parse_unwinder_command_args(arg) if locus_re.match("global"): self.list_unwinders("Global:", gdb.frame_unwinders, name_re) if locus_re.match("progspace"): cp = gdb.current_progspace() self.list_unwinders("Progspace %s:" % cp.filename, cp.frame_unwinders, name_re) for objfile in gdb.objfiles(): if locus_re.match(objfile.filename): self.list_unwinders("Objfile %s:" % objfile.filename, objfile.frame_unwinders, name_re)
def get_type_recognizers(): "Return a list of the enabled type recognizers for the current context." result = [] # First try the objfiles. for objfile in gdb.objfiles(): _get_some_type_recognizers(result, objfile.type_printers) # Now try the program space. _get_some_type_recognizers(result, gdb.current_progspace().type_printers) # Finally, globals. _get_some_type_recognizers(result, gdb.type_printers) return result
def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" (object_re, name_re, subname_re) = parse_printer_regexps(arg) self.invoke1("global pretty-printers:", gdb.pretty_printers, "global", object_re, name_re, subname_re) cp = gdb.current_progspace() self.invoke1("progspace %s pretty-printers:" % cp.filename, cp.pretty_printers, "progspace", object_re, name_re, subname_re) for objfile in gdb.objfiles(): self.invoke1(" objfile %s pretty-printers:" % objfile.filename, objfile.pretty_printers, objfile.filename, object_re, name_re, subname_re)
def exe(self): """ Returns the debugged file name. On remote targets, this may be prefixed with "target:" string. See this by executing those in two terminals: 1. gdbserver 127.0.0.1:1234 /bin/ls 2. gdb -ex "target remote :1234" -ex "pi pwndbg.proc.exe" If you need to process the debugged file use: `pwndbg.file.get_file(pwndbg.proc.exe)` """ return gdb.current_progspace().filename
def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" for name in arg.split(): ok = False for objfile in gdb.objfiles(): if self.set_some(name, objfile.type_printers): ok = True if self.set_some(name, gdb.current_progspace().type_printers): ok = True if self.set_some(name, gdb.type_printers): ok = True if not ok: print ("No type printer named '%s'" % name)
def set_xm_status(arg, status): """Set the status (enabled/disabled) of xmethods matching ARG. This is a helper function for enable/disable commands. ARG is the argument string passed to the commands. """ locus_re, matcher_re, name_re = parse_xm_command_args(arg) set_xm_status1(get_global_method_matchers(locus_re, matcher_re), name_re, status) set_xm_status1( get_method_matchers_in_loci([gdb.current_progspace()], locus_re, matcher_re), name_re, status) set_xm_status1( get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), name_re, status)
def invoke(self, arg, _from_tty): self.dont_repeat() assert arg == '' # Store the currently loaded maps inside the Progspace object, so that we can compare # old and new states. See: # https://sourceware.org/gdb/current/onlinedocs/gdb/Progspaces-In-Python.html progspace = gdb.current_progspace() if not hasattr(progspace, 'debug_maps'): progspace.debug_maps = {} old = progspace.debug_maps new = retrieve_debug_maps() for load_addr in set(old) | set(new): # Skip unload/reload if the map is unchanged if old.get(load_addr) == new.get(load_addr): continue if load_addr in old: # Log the removing, because remove-symbol-file itself doesn't produce helpful output # on errors. file_name, text_addr, sections = old[load_addr] print("Removing symbol file (was {}) from addr: 0x{:x}".format( file_name, load_addr)) try: gdb.execute( 'remove-symbol-file -a 0x{:x}'.format(text_addr)) except gdb.error as e: print( 'warning: failed to remove symbol file: {}'.format(e)) # Note that we escape text arguments to 'add-symbol-file' (file name and section names) # using shlex.quote(), because GDB commands use a shell-like argument syntax. if load_addr in new: file_name, text_addr, sections = new[load_addr] cmd = 'add-symbol-file {} 0x{:x} '.format( shlex.quote(file_name), text_addr) cmd += ' '.join('-s {} 0x{:x}'.format(shlex.quote(name), addr) for name, addr in sections if name != '.text') try: # Temporarily disable pagination, because 'add-symbol-file` produces a lot of # noise. gdb.execute('push-pagination off') gdb.execute(cmd) finally: gdb.execute('pop-pagination') progspace.debug_maps = new
def do_enable_unwinder(arg, flag): """Enable/disable unwinder(s).""" (locus_re, name_re) = parse_unwinder_command_args(arg) total = 0 if locus_re.match("global"): total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag) if locus_re.match("progspace"): total += do_enable_unwinder1(gdb.current_progspace().frame_unwinders, name_re, flag) for objfile in gdb.objfiles(): if locus_re.match(objfile.filename): total += do_enable_unwinder1(objfile.frame_unwinders, name_re, flag) print("%d unwinder%s %s" % (total, "" if total == 1 else "s", "enabled" if flag else "disabled"))
def stop(self, bp): res = gdb.execute('show args', to_string=True) args = [gdb.current_progspace().filename] try: arg_str = str(next(re.finditer('"((?:\\"|[^\"])*)"', res))[1]) args.extend(re.split('(?<!\\\\) ', arg_str)) except StopIteration: pass fr = gdb.selected_frame() ptr_size = int(str(gdb.parse_and_eval('sizeof(char*)'))) buffer_address = 0 buffer_size = 0 try: buffer_address = int(str(gdb.parse_and_eval('&argv_buffer'))) buffer_size = int(str(gdb.parse_and_eval('sizeof(argv_buffer)'))) except: buffer_size = sum(len(arg) + 1 + ptr_size for arg in args) buffer_address = int(str(gdb.parse_and_eval('malloc({})'.format(buffer_size))), 16) used_args = 0 needed_size = 0 for arg in args: nsize = needed_size + ptr_size + len(arg.encode()) + 1 if nsize > buffer_size: print("***metal.gdb***: Couldn't write all of argv, buffer size was {}".format(buffer_size), file=sys.stderr) args = args[used_args:] needed_size = nsize used_args = used_args + 1 endian = 'little' if gdb.execute('show endian', to_string=True).find('little') != -1 else 'big' data_offset = buffer_address + (ptr_size * used_args) data = bytes() for arg in args: data = data + data_offset.to_bytes(ptr_size, endian) data_offset = data_offset + len(arg.encode()) + 1 data = data + b''.join(arg.encode() + b'\x00' for arg in args) assert len(data) <= buffer_size gdb.selected_inferior().write_memory(buffer_address, data) gdb.parse_and_eval('argc = {}'.format(len(args))) gdb.parse_and_eval('argv = (char**){}'.format(buffer_address))
def continue_stage(self): cont = self.controller cont.disable_breakpoint(self) if not gdb.current_progspace().filename: elf = self.stage.elf gdb.execute("file %s" % elf) cont.gdb_print('loaded file %s\n' % elf) cont.gdb_print("Inserting breakpoints for %s %s ...\n" % (self.controller.name, self.stage.stagename)) cont.current_substage = 0 cont.insert_breakpoints(self.stage) cont.gdb_print("Done setting breakpoints\n") for s in self.controller.stage_hooks: s(self, self.stage)
def count_all_enabled_printers(): """Return a 2-tuble of the enabled state and total number of all printers. This includes subprinters. """ enabled_count = 0 total_count = 0 (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers) enabled_count += t_enabled total_count += t_total (t_enabled, t_total) = count_enabled_printers(gdb.current_progspace().pretty_printers) enabled_count += t_enabled total_count += t_total for objfile in gdb.objfiles(): (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers) enabled_count += t_enabled total_count += t_total return (enabled_count, total_count)
def invoke(self, arg, from_tty): any_printed = self.print_list("global frame-filters:", gdb.frame_filters, True) cp = gdb.current_progspace() any_printed += self.print_list( "progspace %s frame-filters:" % cp.filename, cp.frame_filters, True) for objfile in gdb.objfiles(): any_printed += self.print_list( "objfile %s frame-filters:" % objfile.filename, objfile.frame_filters, False, ) if any_printed == 0: print("No frame filters.")
def setup_breakpoints(self, startbreak, stage): c = self.controller if not gdb.current_progspace().filename: gdb.execute("file %s" % stage.elf) sname = stage.stagename if (sname in self.stage_logs.iterkeys()) and self.stage_logs[sname]: global open_log open_log = open(self.stage_logs[sname], 'w') self.results_written = False functions = utils.get_c_function_names(stage) sname = stage.stagename hasblacklist = sname in self.blacklisted.iterkeys() for (name, addr) in functions: if (not hasblacklist) or (hasblacklist and (name not in self.blacklisted[stage.stagename])): norec = name in self.no_rec_funs CallEntryBreak(name, c, stage, norec)
return None t1_name = method_name[4:-1] try: t1_type = gdb.lookup_type(t1_name) return G_mul_worker(t_type, t1_type) except gdb.error: return None global_dm_list = [ SimpleXMethodMatcher( "A_plus_A", "^dop::A$", "operator\+", A_plus_A, # This is a replacement, hence match the arg type # exactly! type_A.const().reference(), ), SimpleXMethodMatcher("plus_plus_A", "^dop::A$", "operator\+\+", plus_plus_A), SimpleXMethodMatcher("A_geta", "^dop::A$", "^geta$", A_geta), SimpleXMethodMatcher("A_getarrayind", "^dop::A$", "^getarrayind$", A_getarrayind, type_int), SimpleXMethodMatcher("A_indexoper", "^dop::A$", "operator\\[\\]", A_indexoper, type_int), SimpleXMethodMatcher("B_indexoper", "^dop::B$", "operator\\[\\]", B_indexoper, type_int), ] for matcher in global_dm_list: gdb.xmethod.register_xmethod_matcher(gdb, matcher) gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), G_methods_matcher()) gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), E_method_matcher())
def get_filename(): return gdb.current_progspace().filename
def get_current_file(self): """Get current file name. """ return gdb.current_progspace().filename
global_dm_list = [ SimpleXMethodMatcher('A_plus_A', '^dop::A$', 'operator\+', A_plus_A, # This is a replacement, hence match the arg type # exactly! type_A.const().reference()), SimpleXMethodMatcher('plus_plus_A', '^dop::A$', 'operator\+\+', plus_plus_A), SimpleXMethodMatcher('A_geta', '^dop::A$', '^geta$', A_geta), SimpleXMethodMatcher('A_getarrayind', '^dop::A$', '^getarrayind$', A_getarrayind, type_int), ] for matcher in global_dm_list: gdb.xmethod.register_xmethod_matcher(gdb, matcher) gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), G_methods_matcher()) gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), E_method_matcher())