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)