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.'''
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
)
18 return match
.groups()[1], match
.groups()[0]
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')
30 gdb_commandline
= 'gdb -batch -x %s 2>/dev/null' % commands
.name
31 gdb_pipe
= os
.popen(gdb_commandline
)
32 result
= gdb_pipe
.readlines()
37 if line
.startswith('Line'):
38 ret
[address_list
[address_count
]] = _GdbOutputToFileLine(line
)
40 if line
.startswith('No line'):
41 ret
[address_list
[address_count
]] = (None, None)
47 class AddressTable(object):
48 ''' Object to do batched line number lookup. '''
50 self
._load
_addresses
= {}
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. '''
61 logging
.warn('adding address %s in empty binary?' % address
)
62 if binary
in self
._binaries
:
63 self
._binaries
[binary
].append(address
)
65 self
._binaries
[binary
] = [address
]
66 self
._all
_resolved
= False
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
83 if self
._all
_resolved
:
84 if binary
in self
._translation
:
85 if addr
in self
._translation
[binary
]:
86 return self
._translation
[binary
][addr
]