def __getitem__(self, name): """ Accessing variables by name. Search order: - current subprogram local data (variables, arguments, ...) - global variables for compile unit of current subprogram TODO: public global variables across all CUs TODO: current CU's subprograms TODO: public global subprograms TODO: target registers :param name: of a variable :returns: corresponding runtime descriptor `Value` """ prog = self.subprogram _locals = prog.data bname = bstr(name) try: datum = _locals[bname] except KeyError: cu = prog.die.cu _globals = self.dic.get_CU_global_variables(cu) try: datum = _globals[bname] except KeyError: raise KeyError("No name '%s' found in runtime" % name) return Value(datum, runtime = self, version = self.version)
def set_br_by_line(self, lineno, cb): line_map = self.rt.dic.find_line_map(bstr(basename(self.srcfile))) line_descs = line_map[lineno] for desc in line_descs: # TODO: set a breakpoint at one address by line number? # if desc.state.is_stmt: addr = self.rt.target.reg_fmt % desc.state.address self.addr2line[addr] = lineno self.rt.add_br(addr, cb)
def failback(self): """ Raises exception and displays the closest mung commits for all breakpoint positions. """ msg = [] re_log = compile(b"<@>(.+?)</@>", flags=S) log_args = ("--pretty=format:</@><@>%H", "--no-merges", "-U0") for fname, lineno, version, delta_intervals in self.failures: log = self.curr_commit.repo.git.log( log_args, "HEAD..%s" % version, "--", fname, p=True)[4:] + "</@>" obstructive_commit = self.find_obstructive_commit( lineno, bstr(log), re_log) if obstructive_commit is None: if delta_intervals[lineno] is not None: new_lineno = self.calc_lineno(delta_intervals, lineno) log = self.curr_commit.repo.git.log( log_args, "%s..HEAD" % version, "--", fname, p=True)[4:] + "</@>" obstructive_commit = self.find_obstructive_commit( new_lineno, bstr(log), re_log) else: msg.append( ("\nThe closest obstructive commit for '%s:%s %s' " "NOT FOUND!" "\nTry decreasing the epsilon (default epsilon = 3).") % (fname, lineno, version)) continue msg.append("\nThe closest obstructive commit for '%s:%s %s': %s" % (fname, lineno, version, obstructive_commit)) raise RuntimeError('\n'.join(msg))
def test_gitpython(self): repo_dir = join(test_dir, "line_adaptation_tests", "gitrepo", "_git") # gitpython launches git during diff obtaining environ["GIT_DIR"] = repo_dir repo = Repo(repo_dir) diff = repo.commit("curr").diff("base", create_patch=True, unified=0) file_name = split(self._new)[0] raw_file_name = bstr(file_name) for change in diff: if change.b_rawpath == raw_file_name: self._check(change.diff) break else: self.fail("No diff for file " + file_name)
def __getitem__(self, name): if self.code == TYPE_CODE_TYPEDEF: return self.target_type[name] members = self.members bname = bstr(name) if bname in members: return members[bname] # A declaration is expected to do not contain members. Hence, try to # find definition and get the member from it. if not self.declaration: raise KeyError("No member '%s'" % name) definition = self.dic[self.name] return definition[name]
def __init__(self, dic, line_adapter=None, verbose=False): """ :type dic: DWARFInfoCache :param line_adapter: is object that specifically converts the line number of a file for some breakpoint position """ self.dic = dic if line_adapter is None: line_adapter = IdentityAdapter() self.verbose = verbose # inspect methods getting those who is a breakpoint handler self.breakpoints = brs = [] for _, cb in getmembers(self, predicate=is_breakpoint_cb): mi = None for mi in breakpoint_matches(cb.__doc__.splitlines()): file_name, lineno, opaque = mi.groups() raw_file_name = bstr(file_name) raw_file_name, line = line_adapter.adapt_lineno( raw_file_name, lineno, opaque) if line is not None: break else: if mi is None: # No position specification was found. # It's not a breakpoint handler. continue try: raw_file_name, line = line_adapter.failback() except Exception as e: # This location format is compatible with PyDev (Eclipse) # and same as one used in standard exception tracebacks. loc_str = ' File "%s", line %d' % cb_loc(cb) raise RuntimeError("Failed to set breakpoint %s\n%s\n%s" % (cb.__name__, loc_str, e)) line_map = dic.find_line_map(raw_file_name) line_descs = line_map[line] for desc in line_descs: addr = desc.state.address brs.append((addr, cb, raw_file_name, line))
def __init__(self, dic, line_adapter=None, verbose=False): """ :type dic: DWARFInfoCache :param line_adapter: is object that specifically converts the line number of a file for some breakpoint position """ self.dic = dic if line_adapter is None: line_adapter = IdentityAdapter() self.verbose = verbose # inspect methods getting those who is a breakpoint handler self.breakpoints = brs = [] for _, cb in getmembers(self, predicate=is_breakpoint_cb): mi = None for mi in breakpoint_matches(cb.__doc__.splitlines()): file_name, lineno, opaque = mi.groups() raw_file_name = bstr(file_name) raw_file_name, line = line_adapter.adapt_lineno( raw_file_name, lineno, opaque) if line is not None: break else: if mi is None: # No position specification was found. # It's not a breakpoint handler. continue raw_file_name, line = line_adapter.failback() line_map = dic.find_line_map(raw_file_name) line_descs = line_map[line] for desc in line_descs: addr = desc.state.address brs.append((addr, cb, raw_file_name, line))
def __getitem__(self, name): sps = self.subprograms bname = bstr(name) if bname in sps: return sps[bname] types = self.types if bname in types: return types[bname] di = self.di # First, search in .debug_pubnames pubnames = self.pubnames if pubnames is None: offsets = None else: offsets = pubnames[name] # Second, search in .debug_pubtypes if offsets is None: pubtypes = self.pubtypes if pubtypes is None: offsets = None else: offsets = pubtypes[name] # Third, search in .symtab if offsets is None: symtab = self.symtab if symtab is None: raise KeyError(name) # Note that `bname` is not required there, `get_symbol_by_name` # can work with strings under both Py2 and Py3. symbols = symtab.get_symbol_by_name(name) if symbols is None: raise KeyError(name) for symbol in symbols: # Get CU that covers target address of current symbol address = symbol.entry.st_value cu = self.cu(address) # Search for a DIE with requested name # TODO: Only topmost DIEs are processed now. Is there a reason # for a deeper search? for die in cu.get_top_DIE().iter_children(): attrs = die.attributes if "DW_AT_name" not in attrs: continue if attrs["DW_AT_name"].value == bname: break else: # No DIE with such name found in current CU continue # A DIE with such name was found break else: # No DIE was found for each symbol with requested name raise KeyError(name) # Note that last cu and die variable definitions are looked for else: cu = di._parse_CU_at_offset(offsets[0]) die = cu.get_DIE_at_offset(offsets[1] - offsets[0]) tag = die.tag[7:] # DW_TAG_* if tag == "subprogram": sym_name = die.attributes["DW_AT_name"].value symbol = Subprogram(self, die, name=sym_name) sps[sym_name] = [symbol] elif tag in TYPE_TAGS: symbol = self.type_by_die(die) else: raise NotImplementedError("Handling name '%s' of DIE tag" " 'DW_TAG_%s' is not implemented yet" % (name, tag)) return symbol