def containsPC(self, address): low = self.get("DW_AT_low_pc", "") if low: high = self.get("DW_AT_high_pc", low) low = fromHex(low) high = fromHex(high) return (address >= low) and (address < high) else: return 0
def getVariableAddress(self, name): if self.objectInfo: node = self.objectInfo.findNode(name) if node: if node.get("DW_AT_location", "").startswith("addr"): return fromHex(node.get("DW_AT_location", "").split()[1][2:]) return 0
def readLineInfo(self, filename): infile = os.popen("dwarfdump -l \"" + filename + "\"", "r") for line in infile: if line == "\n" or line.startswith(".debug_line: line number info") or line.startswith("Source lines") or line.strip().startswith("IS=val") or line.startswith("<pc>") or line.strip().startswith("NS") or line.strip().startswith("PE") or line.startswith(" Line table is") : continue elif line.startswith("No DWARF information"): print line.replace("\n", "") break line = line[0:-1] parts = line.split() try: parts.remove('[') except: pass if parts[0].startswith("0x"): address = fromHex(parts[0][2:]) else: address = int(parts[0]) if address == 0: break if parts[1][0:].startswith("["): location = parts[1][1:].split(",") else: location = parts[1][0:].split(",") try: absFilepath = parts[5] if absFilepath == "": absFilepath = source else: if absFilepath == "uri:": absFilepath = parts[6] source = absFilepath else: source = absFilepath except: source = absFilepath #print "%s %s %s %d" % (parts[0][0:], address, source, int(location[0])) entry = address, source.replace('\"',''), int(location[0]) # Stop loading line info if we get a zero address. The ELF hasn't been linked if address == 0: break self.addressInfo.add(entry) infile.close()
def get(self, name, default=None, depth=0): base = self.pt.node_attribute_first[self.object_id] num = self.pt.node_attribute_num[self.object_id] match = self.pt.string_to_index(name) for i in xrange(num): a = base + i*2 if match == self.pt.attributes[a]: return self.pt.index_to_string(self.pt.attributes[a+1]) if (name != "DW_AT_abstract_origin") and (depth < 10): origin = self.get("DW_AT_abstract_origin", "", depth+1) if origin: offset = int(fromHex(origin[1:-1])) compile_unit = self.pt.object_id_to_compile_unit[self.object_id] object_id = self.pt.compile_unit_offset_to_object_id[(compile_unit,offset)] return DebugObjectInfo(object_id, self.pt).get(name, default, depth+1) if default == None: raise AttributeError() else: return default
def readDwarfTree(self, filename): TMP_FILE = "top_debuginfo_%s.tmp" % (filename.split('/')[-1]) self.attributes = array.array('i') self.node_type = array.array('i') self.node_attribute_first = array.array('i') self.node_attribute_num = array.array('i') self.node_child_first = array.array('i') self.node_next_sibling = array.array('i') node_id_mapping = {} # This is the root node of the tree self.node_type.append(self.string_to_index("root")) self.node_attribute_first.append(0) self.node_attribute_num.append(0) self.node_child_first.append(-1) self.node_next_sibling.append(-1) node_id_mapping[0] = 0 last_children = [-1] parent = [0] scope = 1 compile_unit = -1 # Regular expression used to extract object node information object_re = re.compile("^< *([0-9]+)><0x([0-9a-f]*)> ([a-zA-Z0-9_\- ]+)$") object_const = re.compile("([a-zA-Z0-9_:%,\- ]+)") print "Creating dwarfdump for %s" % filename if not os.path.isfile(TMP_FILE): os.system("dwarfdump -i \"" + filename + "\" > " + TMP_FILE) print "Reading Dwarftree" lineno = 0 infile = open(TMP_FILE, "r") for line in infile: lineno += 1 if (lineno & 0xfffff) == 0: self.showProgress(infile, ".") # Strip the newline line = line[0:-1] constMatch = object_const.match(line) if line.strip() == "": continue # Found an attribute for an object elif line[0:20] == " ": if line.strip().count(" ") < 1: (attrib, value) = (line.strip(), "") else: (attrib, value) = line.strip().split(" ", 1) if "DW_OP_reg" in value: for i in xrange(31, -1, -1): value = value.replace(REGISTER_REF[i], REGISTER_NAMES[i]) self.attributes.append(self.string_to_index(attrib)) self.attributes.append(self.string_to_index(value)) self.node_attribute_num[-1] += 1 elif line[0:2] == "\t\t": continue # Begin a new object elif line[0] == '<': assert(len(parent) == scope) assert(len(last_children) == scope) match = object_re.match(line) obj_scope = int(match.group(1))+1 self.node_type.append(self.string_to_index(match.group(3))) self.node_attribute_first.append(len(self.attributes)) self.node_attribute_num.append(0) self.node_child_first.append(-1) self.node_next_sibling.append(-1) current_object = len(self.node_type)-1 node_id_mapping[int(fromHex(match.group(2)))] = current_object self.object_id_to_compile_unit[current_object] = compile_unit self.compile_unit_offset_to_object_id[(compile_unit,int(fromHex(match.group(2))))] = current_object # Figure out what level of the tree we need to be in if obj_scope == scope: assert(scope > 0) p = parent[scope-1] # This object is a sibling to the current object if last_children[scope-1] == -1: assert(self.node_next_sibling[p] == -1) assert(self.node_child_first[p] == -1) self.node_child_first[p] = current_object else: assert(self.node_child_first[p] != -1) assert(self.node_next_sibling[last_children[scope-1]] == -1) self.node_next_sibling[last_children[scope-1]] = current_object last_children[scope-1] = current_object elif obj_scope == scope + 1: # This object is a child of the current object parent.append(current_object-1) assert(self.node_child_first[parent[scope]] == -1) assert(self.node_next_sibling[parent[scope]] == -1) self.node_child_first[parent[scope]] = current_object last_children.append(current_object) scope = obj_scope elif obj_scope < scope: # This child is from a different root scope = obj_scope parent = parent[0:scope] last_children = last_children[0:scope] p = parent[scope-1] if last_children[scope-1] == -1: assert(self.node_next_sibling[p] == -1) assert(self.node_child_first[p] == -1) self.node_child_first[p] = current_object else: assert(self.node_child_first[p] != -1) assert(self.node_next_sibling[last_children[scope-1]] == -1) self.node_next_sibling[last_children[scope-1]] = current_object last_children[scope-1] = current_object else: # This should be impossible raise Exception("Scoping error") # Begin a new compile unit. All tables reset elif line[0:12] == "COMPILE_UNIT": self.fix_node_numbers(node_id_mapping) node_id_mapping = {} scope = 1 parent = parent[0:scope] last_children = last_children[0:scope] compile_unit += 1 # Skip some useless lines elif line in [".debug_info", "LOCAL_SYMBOLS:"]: pass elif constMatch: parts = constMatch.groups() #print parts[0] continue else: raise Exception("Unexpected input: " + line) infile.close() self.fix_node_numbers(node_id_mapping)