Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / pyelftools / examples / dwarf_decode_address.py
1 #-------------------------------------------------------------------------------
2 # elftools example: dwarf_decode_address.py
3 #
4 # Decode an address in an ELF file to find out which function it belongs to
5 # and from which filename/line it comes in the original source file.
6 #
7 # Eli Bendersky (eliben@gmail.com)
8 # This code is in the public domain
9 #-------------------------------------------------------------------------------
10 from __future__ import print_function
11 import sys
12
13 # If elftools is not installed, maybe we're running from the root or examples
14 # dir of the source distribution
15 try:
16     import elftools
17 except ImportError:
18     sys.path.extend(['.', '..'])
19
20 from elftools.common.py3compat import maxint, bytes2str
21 from elftools.elf.elffile import ELFFile
22
23
24 def process_file(filename, address):
25     print('Processing file:', filename)
26     with open(filename, 'rb') as f:
27         elffile = ELFFile(f)
28
29         if not elffile.has_dwarf_info():
30             print('  file has no DWARF info')
31             return
32
33         # get_dwarf_info returns a DWARFInfo context object, which is the
34         # starting point for all DWARF-based processing in pyelftools.
35         dwarfinfo = elffile.get_dwarf_info()
36
37         funcname = decode_funcname(dwarfinfo, address)
38         file, line = decode_file_line(dwarfinfo, address)
39
40         print('Function:', bytes2str(funcname))
41         print('File:', bytes2str(file))
42         print('Line:', line)
43
44
45 def decode_funcname(dwarfinfo, address):
46     # Go over all DIEs in the DWARF information, looking for a subprogram
47     # entry with an address range that includes the given address. Note that
48     # this simplifies things by disregarding subprograms that may have 
49     # split address ranges.
50     for CU in dwarfinfo.iter_CUs():
51         for DIE in CU.iter_DIEs():
52             try:
53                 if DIE.tag == 'DW_TAG_subprogram':
54                     lowpc = DIE.attributes['DW_AT_low_pc'].value
55                     highpc = DIE.attributes['DW_AT_high_pc'].value
56                     if lowpc <= address <= highpc:
57                         return DIE.attributes['DW_AT_name'].value
58             except KeyError:
59                 continue
60     return None
61
62
63 def decode_file_line(dwarfinfo, address):
64     # Go over all the line programs in the DWARF information, looking for
65     # one that describes the given address.
66     for CU in dwarfinfo.iter_CUs():
67         # First, look at line programs to find the file/line for the address
68         lineprog = dwarfinfo.line_program_for_CU(CU)
69         prevaddr = maxint
70         for entry in lineprog.get_entries():
71             # We're interested in those entries where a new state is assigned
72             state = entry.state
73             if state is not None and not state.end_sequence:
74                 if prevaddr <= address <= state.address:
75                     filename = lineprog['file_entry'][state.file - 1].name
76                     line = state.line
77                     return filename, line
78                 prevaddr = state.address
79     return None, None
80
81
82 if __name__ == '__main__':
83     for filename in sys.argv[1:]:
84         # For testing we use a hardcoded address.
85         process_file(filename, 0x400503)
86