def get_func_with_params(self): """ Dump the debugging info section. """ self._init_dwarfinfo() if self._dwarfinfo is None: return section_offset = self._dwarfinfo.debug_info_sec.global_offset # Offset of the .debug_info section in the stream for cu in self._dwarfinfo.iter_CUs(): funcDic = {} paraCount = 0 funcName="" funcAddr="" for die in cu.iter_DIEs(): if die.abbrev_code == 0 and funcName != "": funcDic[(funcName,funcAddr)] = [paraCount] funcName = "" if die.tag == 'DW_TAG_subprogram': paraCount=0 for attr in itervalues(die.attributes): if 'DW_AT_low_pc' in attr.name: funcAddr=describe_attr_value(attr, die, section_offset).split()[0] if 'DW_AT_name' in attr.name: funcName=describe_attr_value(attr, die, section_offset).split()[-1] elif die.tag == 'DW_TAG_formal_parameter': paraCount+=1 #funcDic.reverse() return funcDic
def get_func_with_params(self): """ Dump the debugging info section. """ self._init_dwarfinfo() if self._dwarfinfo is None: return section_offset = self._dwarfinfo.debug_info_sec.global_offset # Offset of the .debug_info section in the stream for cu in self._dwarfinfo.iter_CUs(): funcDic = {} paraCount = 0 funcName = "" funcAddr = "" for die in cu.iter_DIEs(): if die.abbrev_code == 0 and funcName != "": funcDic[(funcName, funcAddr)] = [paraCount] funcName = "" if die.tag == 'DW_TAG_subprogram': paraCount = 0 for attr in itervalues(die.attributes): if 'DW_AT_low_pc' in attr.name: funcAddr = describe_attr_value( attr, die, section_offset).split()[0] if 'DW_AT_name' in attr.name: funcName = describe_attr_value( attr, die, section_offset).split()[-1] elif die.tag == 'DW_TAG_formal_parameter': paraCount += 1 #funcDic.reverse() return funcDic
def _print_die(die, section_offset): DEBUG("Processing DIE: {}".format(str(die))) for attr in itervalues(die.attributes): if attr.name == 'DW_AT_name' : variable_name = attr.value name = attr.name if isinstance(name, int): name = 'Unknown AT value: %x' % name DEBUG(' <%x> %-18s: %s' % (attr.offset, name, describe_attr_value(attr, die, section_offset)))
def _print_die(die, section_offset): DEBUG("Processing DIE: {}".format(str(die))) for attr in itervalues(die.attributes): if attr.name == 'DW_AT_name': variable_name = attr.value name = attr.name if isinstance(name, int): name = 'Unknown AT value: %x' % name DEBUG(' <%x> %-18s: %s' % (attr.offset, name, describe_attr_value(attr, die, section_offset)))
def _dump_debug_info(self): """ Dump the debugging info section. """ self._emitline('Contents of the .debug_info section:\n') # Offset of the .debug_info section in the stream section_offset = self._dwarfinfo.debug_info_sec.global_offset for cu in self._dwarfinfo.iter_CUs(): self._emitline(' Compilation Unit @ offset %s:' % self._format_hex(cu.cu_offset)) self._emitline(' Length: %s (%s)' % ( self._format_hex(cu['unit_length']), '%s-bit' % cu.dwarf_format())) self._emitline(' Version: %s' % cu['version']), self._emitline(' Abbrev Offset: %s' % ( self._format_hex(cu['debug_abbrev_offset']))), self._emitline(' Pointer Size: %s' % cu['address_size']) # The nesting depth of each DIE within the tree of DIEs must be # displayed. To implement this, a counter is incremented each time # the current DIE has children, and decremented when a null die is # encountered. Due to the way the DIE tree is serialized, this will # correctly reflect the nesting depth # die_depth = 0 for die in cu.iter_DIEs(): self._emitline(' <%s><%x>: Abbrev Number: %s%s' % ( die_depth, die.offset, die.abbrev_code, (' (%s)' % die.tag) if not die.is_null() else '')) if die.is_null(): die_depth -= 1 continue for attr in itervalues(die.attributes): name = attr.name # Unknown attribute values are passed-through as integers if isinstance(name, int): name = 'Unknown AT value: %x' % name self._emitline(' <%2x> %-18s: %s' % ( attr.offset, name, describe_attr_value( attr, die, section_offset))) if die.has_children: die_depth += 1 self._emitline()
def compile(self): """Compile the vtypes from the dwarf information.""" # We currently dump all compilation units into the same # vtype. Technically the same symbol can be defined differently in # different compilation units, but rekall does not have CU # resolution right now so we assume they are all the same. parents = [] section_offset = self._dwarfinfo.debug_info_sec.global_offset for cu in self._dwarfinfo.iter_CUs(): parents.append(cu) die_depth = 0 for die in cu.iter_DIEs(): self.logging.debug( "%d %s<%x>: %s" % (die_depth, "\t" * die_depth, die.offset, ("%s" % die.tag) if not die.is_null() else "") ) if die.is_null(): die_depth -= 1 parents = parents[:-1] continue for attr in itervalues(die.attributes): name = attr.name # Unknown attribute values are passed-through as integers if isinstance(name, int): name = "Unknown AT value: %x" % name if self.logging.isEnabledFor(logging.DEBUG): try: self.logging.debug( "%d %s <%2x> %-18s: %s" % ( die_depth, "\t" * die_depth, attr.offset, name, describe_attr_value(attr, die, section_offset), ) ) except Exception: pass # Record the type in this DIE. t = self.types[die.offset] = DIEFactory(die, self.types, parents) if die.has_children: parents.append(t) die_depth += 1
def compile(self): """Compile the vtypes from the dwarf information.""" # We currently dump all compilation units into the same # vtype. Technically the same symbol can be defined differently in # different compilation units, but rekall does not have CU # resolution right now so we assume they are all the same. parents = [] section_offset = self._dwarfinfo.debug_info_sec.global_offset for cu in self._dwarfinfo.iter_CUs(): parents.append(cu) die_depth = 0 for die in cu.iter_DIEs(): self.logging.debug('%d %s<%x>: %s' % ( die_depth, "\t" * die_depth, die.offset, ('%s' % die.tag) if not die.is_null() else '')) if die.is_null(): die_depth -= 1 parents = parents[:-1] continue for attr in itervalues(die.attributes): name = attr.name # Unknown attribute values are passed-through as integers if isinstance(name, int): name = 'Unknown AT value: %x' % name if self.logging.isEnabledFor(logging.DEBUG): try: self.logging.debug('%d %s <%2x> %-18s: %s' % ( die_depth, "\t" * die_depth, attr.offset, name, describe_attr_value( attr, die, section_offset))) except Exception: pass # Record the type in this DIE. t = self.types[die.offset] = DIEFactory( die, self.types, parents) if die.has_children: parents.append(t) die_depth += 1
def _dump_debug_info(self): """ Dump the debugging info section. """ self._emitline('Contents of the .debug_info section:\n') # Offset of the .debug_info section in the stream section_offset = self._dwarfinfo.debug_info_sec.global_offset for cu in self._dwarfinfo.iter_CUs(): self._emitline(' Compilation Unit @ offset %s:' % self._format_hex(cu.cu_offset)) self._emitline(' Length: %s (%s)' % (self._format_hex( cu['unit_length']), '%s-bit' % cu.dwarf_format())) self._emitline(' Version: %s' % cu['version']), self._emitline(' Abbrev Offset: %s' % cu['debug_abbrev_offset']), self._emitline(' Pointer Size: %s' % cu['address_size']) # The nesting depth of each DIE within the tree of DIEs must be # displayed. To implement this, a counter is incremented each time # the current DIE has children, and decremented when a null die is # encountered. Due to the way the DIE tree is serialized, this will # correctly reflect the nesting depth # die_depth = 0 for die in cu.iter_DIEs(): if die.is_null(): die_depth -= 1 continue self._emitline( ' <%s><%x>: Abbrev Number: %s (%s)' % (die_depth, die.offset, die.abbrev_code, die.tag)) for attr in itervalues(die.attributes): name = attr.name # Unknown attribute values are passed-through as integers if isinstance(name, int): name = 'Unknown AT value: %x' % name self._emitline( ' <%2x> %-18s: %s' % (attr.offset, name, describe_attr_value(attr, die, section_offset))) if die.has_children: die_depth += 1 self._emitline()
def _get_attribute_description(self, attr, die): """ Use regex to parse attribute description (value) """ description = describe_attr_value(attr, die, 0) regex_pattern = "" if "DW_AT_name" == attr.name: regex_pattern = "^([\w ]+\t)|: ([\w ]+\t)$" elif "DW_AT_type" == attr.name: regex_pattern = "^<(0x[\da-fA-F]+)>\t$" elif "DW_AT_location" == attr.name: regex_pattern = ".*DW_OP_addr: ([\w]+)" elif "DW_AT_data_member_location" == attr.name: regex_pattern = "^([\d]+\t)$" elif "DW_AT_byte_size" == attr.name: regex_pattern = "^([\d]+\t)$" if "" != regex_pattern: match = re.compile(regex_pattern) match = match.search(description) if match: match_group = match.groups() if attr.name in ["DW_AT_type", "DW_AT_location"]: description = match_group[0].rstrip() description = int(description, 16) elif attr.name in [ "DW_AT_data_member_location", "DW_AT_byte_size" ]: description = match_group[0].rstrip() description = int(description) elif attr.name in ["DW_AT_name"]: index = [ match for match in range(len(match_group)) if match_group[match] != None ] description = match_group[index[0]].rstrip() else: pass else: description = description.rstrip() else: description = None return description
def _attr_to_dict(self, die): attrs_raw = { attr[0]: attr for attr in [( attr.name, attr.offset, describe_attr_value(attr, die, self.section_offset).strip()) for attr in itervalues(die.attributes)] } attrs = objdict() attrs.tag = die.tag for i in attrs_raw: attrs[i] = attrs_raw[i][2].strip() if self.DW_AT_TYPE in attrs_raw: typestr = attrs_raw[self.DW_AT_TYPE][2].strip() typeint = int(typestr[1:len(typestr) - 1], 16) attrs.DW_AT_type = typeint if self.DW_AT_NAME in attrs and attrs.DW_AT_name.startswith( "(indirect string, offset:"): attrs.DW_AT_name = attrs.DW_AT_name.split(":")[2].strip() attrs.raw_die = die attrs.offset = die.offset return attrs
def parse_compile_unit(die): """parse a compile unit (usually at the top). A compile unit (in xml) looks like the following: <abi-instr version='1.0' address-size='64' path='../../src/abg-regex.cc' comp-dir-path='/libabigail-1.8/build/src' language='LANG_C_plus_plus'> TODO: we can map numbers to languages here. """ language = describe_attr_value(die.attributes["DW_AT_language"], die, die.offset) dmeta = { "_type": "abi-instr", "version": __version__, # Multiply by 8 to go from bytes to bits "address-size": die.cu.header["address_size"] * 8, "path": bytes2str(die.attributes["DW_AT_name"].value), "language": language, "comp-dir-path": bytes2str(die.attributes["DW_AT_comp_dir"].value), } if die.has_children: dmeta["children"] = [] return dmeta
rr = collections.OrderedDict() rr['die_depth'] = die_depth rr['offset'] = die.offset rr['abbrev_code'] = die.abbrev_code rr['die_null'] = die.is_null() rr['section_offset'] = section_offset if die.is_null(): die_depth -= 1 continue for attr in itervalues(die.attributes): r = collections.OrderedDict() name = attr.name # Unknown attribute values are passed-through as integers if isinstance(name, int): raise ValueError("Unknown attribute") r['name'] = name r['attr_offset'] = attr.offset r['attr_value'] = describe_attr_value(attr, die, section_offset) r['has_child'] = die.has_children r.update(rr) if die.has_children: die_depth += 1 data.append(r)
def testit(names, variables): def nonesorter(a): if a[0] is None: return '', a[1] return a with open('output.txt', 'w') as f: for name, item in sorted(names.items(), key=nonesorter): i = item logging.debug('{}: {}'.format(name, i), file=f) import operator logging.debug('\n'.join( str(v) for v in sorted(variables, key=operator.attrgetter('name')))) logging.debug(names['Vholdoff'].render()) logging.debug(names['ozFpga'].render()) logging.debug(names['FpgaRegs'].render()) logging.debug(names['writingEE'].render()) logging.debug(names['rxStart'].render()) logging.debug(dereference(names['rxStart']).render()) logging.debug(names['POR_Flags'].render()) logging.debug(names['IEEE_1547_FreqLimit'].render()) # logging.debug(base_type(names['IEEE_1547_FreqLimit']).format_string()) a = b'\x01\x02\x03\x04' b = b'\x05\x06\x07\x08' c = a + b # logging.debug(base_type(names['IEEE_1547_FreqLimit']).unpack(c)) logging.debug((int.from_bytes(a, byteorder='little'), int.from_bytes(b, byteorder='little'))) data = b'\x00\xd1\x01\x44\x00\x06\x00\x00\x00\x07\x00\x08\x28\x09\x00\xb0' # data = bytes(ccp.endianness_swap_2byte(data_raw))#b'\xd1\x00\x44\x01\x06\x00\x00\x00' # logging.debug(data) # logging.debug(''.join(['{:08b}'.format(b) for b in data])) logging.debug(names['TestStruct'].render()) import pprint pp = pprint.PrettyPrinter(indent=4) logging.debug(pp.pformat(base_type(names['TestStruct']).padded_members())) # logging.debug(base_type(names['TestStruct']).format_string()) logging.debug(bytearray_to_bits(data)) logging.debug(pp.pformat(base_type(names['TestStruct']).unpack(data))) data = bytearray(data) for member in base_type(names['TestStruct']).padded_members(): type = base_type(member) if member.bit_offset is None: byte = member.location * bits_per_byte // 8 s = slice(byte, byte + type.bytes * bits_per_byte // 8) # logging.debug('slice: {}'.format(s)) # logging.debug(data) data[s] = ccp.endianness_swap_2byte(data[s]) # logging.debug(data) # | | | | | | logging.debug( pp.pformat( bitstruct.unpack( '<p4>u6>u3>u3<p4>u6>u6<u32<p6>u10<u16<p2>u10<u10<u10', data))) logging.debug('-----------------------------') logging.debug('-----------------------------') logging.debug('-----------------------------') data = collections.OrderedDict() data['TestStruct1'] = b'\x03\xFF\x00\x00' data['TestStruct2'] = b'\xFF\xFF\x00\x0F' data['TestStruct3'] = b'\xFF\xFF\x3F\xFF' data['TestStruct4'] = b'\x03\xFF' data['TestStruct5'] = b'\x03\xFF\x00\x00\x00\x00\x00\x00' data['TestStruct6'] = b'\xFF\xFF\x00\x0F\x00\x00\x00\x00' data['TestStruct7'] = b'\xFF\xFF\x3F\xFF\x00\x00\x00\x00' data['TestStruct8'] = b'\xFF\xFF\xFF\xFF\x00\xFF\x00\x00' data['TestStruct9'] = b'\xFF\xFF\xFF\xFF\xFF\xFF\x00\x03' data['TestStruct10'] = b'\xFF\xFF\xFF\xFF\xFF\xFF\x0F\xFF' data['TestStruct11'] = b'\xFF\xFF\xFF\xFF\xFF\xFF\x0F\xFF\x44\x05\x00\x00' data[ 'TestStruct12'] = b'\xFF\xFF\xFF\xFF\xFF\xFF\x0F\xFF\x44\x05\x00\x00\x00\x2A\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00' # huh? 6 entries listed in the debugger for a 5 entry array? data[ 'testArray1'] = b'\x00\x0B\x00\x00\x00\x16\x00\x00\x00\x21\x00\x00\x00\x2C\x00\x00\x00\x37\x00\x00' #\x00\x05\x35\x4A' for name in data.keys( ): #['TestStruct{}'.format(i) for i in [1,2,3,4,5,6,7,8,9,10,11]]: logging.debug(names[name].render()) base = base_type(names[name]) if hasattr(base, 'padded_members'): logging.debug(pp.pformat(base.padded_members())) # logging.debug(base_type(names[name]).format_string()) logging.debug(bytearray_to_bits(data[name])) logging.debug(pp.pformat(base.unpack(data[name]))) # data = bytearray(data) # for member in base_type(names[name]).padded_members(): # type = base_type(member) # if member.bit_offset is None: # byte = member.location * bits_per_byte // 8 # s = slice(byte, byte + type.bytes * bits_per_byte // 8) # # logging.debug('slice: {}'.format(s)) # # logging.debug(data) # data[s] = ccp.endianness_swap_2byte(data[s]) # # logging.debug(data) # # logging.debug(pp.pformat(bitstruct.unpack('<p2<u10<u10<u10', # data))) logging.debug('\n\n-----------------------------\n\n') logging.debug('-----------------------------') logging.debug('-----------------------------') logging.debug('-----------------------------') return logging.debug(names['Relay'].render()) # logging.debug(base_type(names['Relay']).bytes) # logging.debug(base_type(names['Relay']).format_string()) data = b'\x00\x48\x00\x00\xd5\x13\x00\x00' logging.debug(pp.pformat(data)) # data = bytes(ccp.endianness_swap_2byte(data)) # <u2<u1<u2<u1<u1<p9<s16<u32 # <u1<u1<u2<u1<u2<p9<s16<u32 # logging.debug(''.join(['{:08b}'.format(b) for b in data])) # logging.debug(bitstruct.unpack('<p1<u1<u1<u2<u1<u2<p8<s16<u32', data)) # logging.debug(bitstruct.unpack('<u1<u2<u1<u2<u1<p9<s16<u32', data)) # logging.debug(bitstruct.unpack('<p9<u1<u1<u2<u1<u2<s16<u32', data)) # logging.debug(pp.pformat(base_type(names['Relay']).padded_members())) logging.debug(pp.pformat(base_type(names['Relay']).unpack(data))) return indent_level = ' ' for tag, items in objects.items(): for die in items: logging.debug('{}: {}'.format( tag, die.attributes['DW_AT_name'].value.decode('utf-8'))) if die.tag == 'DW_TAG_structure_type': logging.debug(indent_level + 'DIE tag=%s' % die.tag) try: logging.debug(indent_level + ' Sibling: ' + str(die.attributes['DW_AT_sibling'].value)) except KeyError: logging.debug(indent_level + ' KeyError on DW_AT_sibling') pass logging.debug(indent_level + ' Offset: ' + str(die.offset)) logging.debug(indent_level + ' File: ' + str(die.attributes['DW_AT_decl_file'].value)) logging.debug(indent_level + ' Line: ' + str(die.attributes['DW_AT_decl_line'].value)) logging.debug(indent_level + ' Attributes: ' + str(die.attributes)) logging.debug(indent_level + ' DIE: ' + str(dir(die))) die_info_rec_structure_type(die, indent_level + ' ') # else: # logging.debug(indent_level + 'DIE tag=%s' % die.tag) elif die.tag == 'DW_TAG_typedef': logging.debug(indent_level + 'DIE tag=%s' % die.tag) try: logging.debug(indent_level + ' Name: ' + str( die.attributes['DW_AT_name'].value.decode('utf-8'))) except KeyError: logging.debug(indent_level + ' KeyError on DW_AT_name') pass logging.debug(indent_level + ' Offset: ' + str(die.offset)) file = die.attributes.get('DW_AT_decl_file', None) if file is not None: file = file.value else: file = 'not found' logging.debug(indent_level + ' File: ' + str(file)) line = die.attributes.get('DW_AT_decl_line', None) if line is not None: line = line.value else: line = 'not found' logging.debug(indent_level + ' Line: ' + str(line)) logging.debug(indent_level + ' Type: ' + str(die.attributes['DW_AT_type'].value)) logging.debug(indent_level + ' describe_attr_value(Type): ' + describe_attr_value(die.attributes['DW_AT_type'], die, die.cu.cu_offset)) logging.debug(indent_level + ' Attributes: ' + str(die.attributes)) logging.debug(indent_level + ' DIE: ' + str(dir(die))) elif die.tag == 'DW_TAG_variable': logging.debug(indent_level + 'DIE tag=%s' % die.tag) else: logging.debug(indent_level + 'DIE tag=%s' % die.tag) logging.debug(indent_level + ' Offset: ' + str(die.offset)) for attribute, value in die.attributes.items(): logging.debug(indent_level + ' {}: {}'.format( attribute, describe_attr_value(die.attributes[attribute], die, die.cu.cu_offset)))