Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# Copyright (C) 2017 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>.
# objdump-based DWARF parser
# TODO: for now, this assumes that there is only one compilation unit per # object file. This should be implemented later if needed.
r'\s+(?P<tag>DW_TAG_[a-zA-Z0-9_]+)' r'\s+\[(?P<has_children>.*)\]') r'\s+(?P<form>DW_FORM(_[a-zA-Z0-9_]+| value: \d+))')
r' (?P<offset>0x[0-9a-f]+):') r'\s+(?P<value>.*)') r'<(?P<offset>[0-9a-f]+)>:' r' Abbrev Number: (?P<abbrev_number>\d+)' r'( \((?P<tag>DW_TAG_[a-zA-Z0-9_]+)\))?') r'\s+(?P<attr>DW_AT_[a-zA-Z0-9_]+)' r'\s*: (?P<value>.*)')
r' (?P<value>.*)') r' (?P<bytes>[0-9a-f ]+)' r'\s+\((?P<expr>.*)\)')
def command_output(argv): # no-coverage """ Dummy re-implementation of `subprocess.check_output`. This function was added in Python 2.7 and we need to support Python 2.6 interpreters.
:param list[str] argv: Command line to run. :rtype: str """ command = argv[0] p = subprocess.Popen( argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = p.communicate() if stderr: print('Running {0} gave a non-empty stderr:'.format(command)) print(stderr) raise RuntimeError('non-empty stderr') if p.returncode != 0: print('Running {0} gave a non-zero return code ({1})'.format( command, p.returncode )) raise RuntimeError('non-zero return code') return stdout
class Objdump(object): # no-coverage """ Runner for objdump to get dumps. """
def __init__(self, object_file): self.object_file = object_file
def _run(self, part): return [ as_ascii(line).rstrip() for line in command_output([dwarfutils.DWARF_DUMP_TOOL, '--dwarf=' + part, self.object_file]).splitlines() if line.strip() ]
def get_info(self): """Run objdump --dwarf=info.""" return self._run('info')
def get_abbrev(self): return self._run('abbrev')
def parse_dwarf(object_file): # no-coverage """ Implementation of dwarfutils.parse_dwarf for objdump.
Run objdump on `object_file` and parse the list compilation units it contains.
:param str object_file: Name of the object file to process. :rtype: list[CompilationUnit] """ return _parse_dwarf(Objdump(object_file))
def parse_abbrevs(object_file): # no-coverage """ Run objdump on `object_file` and parse the list of abbreviations it contains.
:param str object_file: Name of the object file to process. :rtype: list[Abbrev] """ return _parse_abbrevs(Objdump(object_file))
""" Implementation of dwarfutils.parse_dwarf for objdump.
Run objdump on `object_file` and parse the list compilation units it contains.
:param str object_file: Name of the object file to process. :rtype: list[CompilationUnit] """
# Try to match the beginning of a compilation unit
' handled for now')
abbrevs_sublist, pointer_size))
# Try to match the beginning of a DIE
# The end of child list is represented as a special DIE with # abbreviation number 0.
die, tag ) else: continue
# Try to match an attribute
else: except ValueError: print('Error while decoding {0} ({1}) at {2:#x}:' ' {3}'.format(name, form, offset, value)) raise
# Otherwise, we must be processing "header" text before the dump # itself: just discard it.
""" Run objdump on `object_file` and parse the list of abbreviations it contains.
:param str object_file: Name of the object file to process. :rtype: list[Abbrev] """
# Try to match a new abbrevation
# Try to match an attribute
# When objdump finds unknown abbreviation numbers or unknown form # numbers, it cannot turn them into names.
# The (0, 0) couple marks the end of the attribute list continue
# Otherwise, we must be processing "header" text before the dump # itself: just discard it.
# Decoders for attribute values
return bool(int(value))
if ( not no_exprloc and name in ('DW_AT_location', 'DW_AT_data_member_location') ): return _decode_exprloc(die, name, form, offset, value, )
m = block_re.match(value) assert m, 'Unhandled block value: {0}'.format(value) return [int(b, 16) for b in m.group('value').split()]
# Even though they have the expected DW_FORM_exploc form, objdump does # not decode some location expressions such as DW_AT_byte_size. In this # case, return a dummy block decoding instead. # TODO: implement raw bytes parsing into expressions instead. return _decode_block(die, name, form, offset, value, no_exprloc=True)
'Unhandled DWARF expression operation: {0}'.format(op) )
'DW_FORM_flag_present': _decode_flag_present, 'DW_FORM_flag': _decode_flag,
'DW_FORM_addr': _decode_data, 'DW_FORM_sec_offset': _decode_data, 'DW_FORM_data1': _decode_data, 'DW_FORM_data2': _decode_data, 'DW_FORM_data4': _decode_data, 'DW_FORM_data8': _decode_data, 'DW_FORM_sdata': _decode_data, 'DW_FORM_udata': _decode_data,
'DW_FORM_ref4': _decode_ref, 'DW_FORM_ref8': _decode_ref,
'DW_FORM_strp': _decode_indirect_string,
'DW_FORM_block': _decode_block, 'DW_FORM_block1': _decode_block, 'DW_FORM_block2': _decode_block, 'DW_FORM_block4': _decode_block, 'DW_FORM_block8': _decode_block, 'DW_FORM_block8': _decode_block, 'DW_FORM_exprloc': _decode_exprloc,
# TODO: handle all existing forms } |