def _add_git_diff(self, version): diff = self.curr_commit.diff(version, "*.c", True, unified=0) self._draft_diffs[version] = {} if diff: for changes in diff: if changes.raw_rename_to: # file renamed val = (changes.diff, changes.a_rawpath) fname = changes.b_rawpath else: if changes.a_rawpath: if changes.b_rawpath: # file exists in both versions fname = changes.a_rawpath val = (changes.diff, None) else: # file exists only in current version continue else: # file exists only in base version fname = changes.b_rawpath # for any lineno delta = None val = (None, None) trie_add(self._draft_diffs[version], tuple(reversed(fname.split(bsep))), val)
def _account_cu_by_reversed_name(self, rparts, cu): # print("Accounting %s" % str(rparts)) if trie_add(self.name2cu, rparts, cu) is not cu: raise RuntimeError("CU with path %s is already accounted" % ( cu.get_top_DIE().attributes["DW_AT_name"].value ))
def get_glv_data(self, version, fname): "data is delta intervals and renaming for `fname`" version_trie = self._cache.setdefault(version, {}) try: return trie_find(version_trie, tuple(reversed(fname.split(bsep))))[0] except KeyError: pass if version not in self._draft_diffs: self._add_git_diff(version) val = self._find_git_diff(version, fname) trie_add(version_trie, tuple(reversed(fname.split(bsep))), val) return val
def account_line_program_CU(self, cu): lp = self.di.line_program_for_CU(cu) entries = lp.get_entries() # Note that program entries must be parsed before header file list # access because DW_LNE_define_file operation adds new file entry # during entries parsing. hdr = lp.header fentries = hdr["file_entry"] # file_names dnames = hdr["include_directory"] # include_directories # first reconstruct contributing file paths files = [] for f in fentries: dir_index = f["dir_index"] if dir_index == 0: # in current directory of the compilation _dir = ["."] else: # in include_directories section of the header _dir = dnames[dir_index - 1].split(bsep) name = f["name"].split(bsep) _path = _dir + name files.append(_path) self.cu_off2files[cu.cu_offset] = files srcmap = self.srcmap # To avoid double srcmap traversing (1. checking if a line map # already for a file and 2. adding a map if not) the attempt to add # an empty line map is always performed. If there is a map for the # file then trie_add returns it. If it returned given empty map then # this file is just added to srcmap and a new empty map should be # prepared for next file. empty_line_map = intervalmap() # cache of file line maps to prevent frequent search in srcmap line_maps = [None] * len(files) for e in entries: s = e.state if not s: # intermediate entries are not interested continue file_idx = s.file - 1 line_map = line_maps[file_idx] if line_map is None: line_map = trie_add(srcmap, tuple(reversed(files[file_idx])), empty_line_map ) line_maps[file_idx] = line_map right_bound = s.line + 1 if line_map is empty_line_map: # new file in srcmap, prepare new empty line map for next file empty_line_map = intervalmap() # This indirectly means that this entry (e) for this file is # first in the loop. Temporally occupy all lines above the line # of this entry. If there are entries whose occupied those # lines then the corresponding interval will be overwritten. # (0 because strange line number comes from LLVM 5.0.0) line_map[0:right_bound] = [e] else: # this file already is in srcmap left, right = line_map.interval(s.line) if right == right_bound: line_map[left].append(e) else: line_map[left: s.line + 1] = [e]