Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / tools / find_runtime_symbols / find_runtime_symbols.py
1 #!/usr/bin/env python
2 # Copyright 2012 The Chromium Authors
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 """Find symbols in a binary corresponding to given runtime virtual addresses.
6
7 Note that source file names are treated as symbols in this script while they
8 are actually not.
9 """
10
11 from __future__ import print_function
12
13 import json
14 import logging
15 import os
16 import sys
17
18 from static_symbols import StaticSymbolsInFile
19
20
21 _BASE_PATH = os.path.dirname(os.path.abspath(__file__))
22 _TOOLS_LINUX_PATH = os.path.join(_BASE_PATH, os.pardir, 'linux')
23 sys.path.insert(0, _TOOLS_LINUX_PATH)
24
25
26 from procfs import ProcMaps  # pylint: disable=F0401
27
28 try:
29   from collections import OrderedDict  # pylint: disable=E0611
30 except ImportError:
31   _SIMPLEJSON_PATH = os.path.join(_BASE_PATH, os.pardir, os.pardir,
32                                   'third_party')
33   sys.path.insert(0, _SIMPLEJSON_PATH)
34   from simplejson import OrderedDict
35
36
37 FUNCTION_SYMBOLS = 0
38 SOURCEFILE_SYMBOLS = 1
39 TYPEINFO_SYMBOLS = 2
40
41 _MAPS_FILENAME = 'maps'
42 _FILES_FILENAME = 'files.json'
43
44
45 class RuntimeSymbolsInProcess:
46   def __init__(self):
47     self.maps = None
48     self._static_symbols_in_filse = {}
49
50   def find_procedure(self, runtime_address):
51     for vma in self.maps.iter(ProcMaps.executable):
52       if vma.begin <= runtime_address < vma.end:
53         static_symbols = self._static_symbols_in_filse.get(vma.name)
54         if static_symbols:
55           return static_symbols.find_procedure_by_runtime_address(
56               runtime_address, vma)
57         return None
58     return None
59
60   def find_sourcefile(self, runtime_address):
61     for vma in self.maps.iter(ProcMaps.executable):
62       if vma.begin <= runtime_address < vma.end:
63         static_symbols = self._static_symbols_in_filse.get(vma.name)
64         if static_symbols:
65           return static_symbols.find_sourcefile_by_runtime_address(
66               runtime_address, vma)
67         return None
68     return None
69
70   def find_typeinfo(self, runtime_address):
71     for vma in self.maps.iter(ProcMaps.constants):
72       if vma.begin <= runtime_address < vma.end:
73         static_symbols = self._static_symbols_in_filse.get(vma.name)
74         if static_symbols:
75           return static_symbols.find_typeinfo_by_runtime_address(
76               runtime_address, vma)
77         return None
78     return None
79
80   @staticmethod
81   def load(prepared_data_dir):
82     symbols_in_process = RuntimeSymbolsInProcess()
83
84     with open(os.path.join(prepared_data_dir, _MAPS_FILENAME), mode='r') as f:
85       symbols_in_process.maps = ProcMaps.load_file(f)
86     with open(os.path.join(prepared_data_dir, _FILES_FILENAME), mode='r') as f:
87       files = json.load(f)
88
89     # pylint: disable=W0212
90     for vma in symbols_in_process.maps.iter(ProcMaps.executable_and_constants):
91       file_entry = files.get(vma.name)
92       if not file_entry:
93         continue
94
95       static_symbols = StaticSymbolsInFile(vma.name)
96
97       nm_entry = file_entry.get('nm')
98       if nm_entry and nm_entry['format'] == 'bsd':
99         with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f:
100           static_symbols.load_nm_bsd(f, nm_entry['mangled'])
101
102       readelf_entry = file_entry.get('readelf-e')
103       if readelf_entry:
104         with open(os.path.join(prepared_data_dir, readelf_entry['file']),
105                   'r') as f:
106           static_symbols.load_readelf_ew(f)
107
108       decodedline_file_entry = file_entry.get('readelf-debug-decodedline-file')
109       if decodedline_file_entry:
110         with open(os.path.join(prepared_data_dir,
111                                decodedline_file_entry['file']), 'r') as f:
112           static_symbols.load_readelf_debug_decodedline_file(f)
113
114       symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols
115
116     return symbols_in_process
117
118
119 def _find_runtime_function_symbols(symbols_in_process, addresses):
120   result = OrderedDict()
121   for address in addresses:
122     if isinstance(address, basestring):
123       address = int(address, 16)
124     found = symbols_in_process.find_procedure(address)
125     if found:
126       result[address] = found.name
127     else:
128       result[address] = '0x%016x' % address
129   return result
130
131
132 def _find_runtime_sourcefile_symbols(symbols_in_process, addresses):
133   result = OrderedDict()
134   for address in addresses:
135     if isinstance(address, basestring):
136       address = int(address, 16)
137     found = symbols_in_process.find_sourcefile(address)
138     if found:
139       result[address] = found
140     else:
141       result[address] = ''
142   return result
143
144
145 def _find_runtime_typeinfo_symbols(symbols_in_process, addresses):
146   result = OrderedDict()
147   for address in addresses:
148     if isinstance(address, basestring):
149       address = int(address, 16)
150     if address == 0:
151       result[address] = 'no typeinfo'
152     else:
153       found = symbols_in_process.find_typeinfo(address)
154       if found:
155         if found.startswith('typeinfo for '):
156           result[address] = found[13:]
157         else:
158           result[address] = found
159       else:
160         result[address] = '0x%016x' % address
161   return result
162
163
164 _INTERNAL_FINDERS = {
165     FUNCTION_SYMBOLS: _find_runtime_function_symbols,
166     SOURCEFILE_SYMBOLS: _find_runtime_sourcefile_symbols,
167     TYPEINFO_SYMBOLS: _find_runtime_typeinfo_symbols,
168     }
169
170
171 def find_runtime_symbols(symbol_type, symbols_in_process, addresses):
172   return _INTERNAL_FINDERS[symbol_type](symbols_in_process, addresses)
173
174
175 def main():
176   # FIX: Accept only .pre data
177   if len(sys.argv) < 2:
178     sys.stderr.write("""Usage:
179 %s /path/to/prepared_data_dir/ < addresses.txt
180 """ % sys.argv[0])
181     return 1
182
183   log = logging.getLogger('find_runtime_symbols')
184   log.setLevel(logging.WARN)
185   handler = logging.StreamHandler()
186   handler.setLevel(logging.WARN)
187   formatter = logging.Formatter('%(message)s')
188   handler.setFormatter(formatter)
189   log.addHandler(handler)
190
191   prepared_data_dir = sys.argv[1]
192   if not os.path.exists(prepared_data_dir):
193     log.warn("Nothing found: %s" % prepared_data_dir)
194     return 1
195   if not os.path.isdir(prepared_data_dir):
196     log.warn("Not a directory: %s" % prepared_data_dir)
197     return 1
198
199   symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir)
200   symbols_dict = find_runtime_symbols(FUNCTION_SYMBOLS,
201                                       symbols_in_process,
202                                       sys.stdin)
203   for address, symbol in symbols_dict.iteritems():
204     if symbol:
205       print('%016x %s' % (address, symbol))
206     else:
207       print('%016x' % address)
208
209   return 0
210
211
212 if __name__ == '__main__':
213   sys.exit(main())