- add sources.
[platform/framework/web/crosswalk.git] / src / tools / valgrind / gdb_helper.py
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 ''' A bunch of helper functions for querying gdb.'''
6
7 import logging
8 import os
9 import re
10 import tempfile
11
12 GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
13
14 def _GdbOutputToFileLine(output_line):
15   ''' Parse the gdb output line, return a pair (file, line num) '''
16   match =  GDB_LINE_RE.match(output_line)
17   if match:
18     return match.groups()[1], match.groups()[0]
19   else:
20     return None
21
22 def ResolveAddressesWithinABinary(binary_name, load_address, address_list):
23   ''' For each address, return a pair (file, line num) '''
24   commands = tempfile.NamedTemporaryFile()
25   commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address))
26   for addr in address_list:
27     commands.write('info line *%s\n' % addr)
28   commands.write('quit\n')
29   commands.flush()
30   gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name
31   gdb_pipe = os.popen(gdb_commandline)
32   result = gdb_pipe.readlines()
33
34   address_count = 0
35   ret = {}
36   for line in result:
37     if line.startswith('Line'):
38       ret[address_list[address_count]] = _GdbOutputToFileLine(line)
39       address_count += 1
40     if line.startswith('No line'):
41       ret[address_list[address_count]] = (None, None)
42       address_count += 1
43   gdb_pipe.close()
44   commands.close()
45   return ret
46
47 class AddressTable(object):
48   ''' Object to do batched line number lookup. '''
49   def __init__(self):
50     self._load_addresses = {}
51     self._binaries = {}
52     self._all_resolved = False
53
54   def AddBinaryAt(self, binary, load_address):
55     ''' Register a new shared library or executable. '''
56     self._load_addresses[binary] = load_address
57
58   def Add(self, binary, address):
59     ''' Register a lookup request. '''
60     if binary == '':
61       logging.warn('adding address %s in empty binary?' % address)
62     if binary in self._binaries:
63       self._binaries[binary].append(address)
64     else:
65       self._binaries[binary] = [address]
66     self._all_resolved = False
67
68   def ResolveAll(self):
69     ''' Carry out all lookup requests. '''
70     self._translation = {}
71     for binary in self._binaries.keys():
72       if binary != '' and binary in self._load_addresses:
73         load_address = self._load_addresses[binary]
74         addr = ResolveAddressesWithinABinary(
75             binary, load_address, self._binaries[binary])
76         self._translation[binary] = addr
77     self._all_resolved = True
78
79   def GetFileLine(self, binary, addr):
80     ''' Get the (filename, linenum) result of a previously-registered lookup
81     request.
82     '''
83     if self._all_resolved:
84       if binary in self._translation:
85         if addr in self._translation[binary]:
86           return self._translation[binary][addr]
87     return (None, None)