Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / tools / valgrind / gdb_helper.py
blob548ee9474e65e08cc36fd8879338afbe39c052f7
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.
5 ''' A bunch of helper functions for querying gdb.'''
7 import logging
8 import os
9 import re
10 import tempfile
12 GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
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
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()
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
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
54 def AddBinaryAt(self, binary, load_address):
55 ''' Register a new shared library or executable. '''
56 self._load_addresses[binary] = load_address
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
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
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)