12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
- #
- # Use of this source code is governed by a BSD-style license
- # that can be found in the LICENSE file in the root of the source
- # tree. An additional intellectual property rights grant can be found
- # in the file PATENTS. All contributing project authors may
- # be found in the AUTHORS file in the root of the source tree.
- ''' A bunch of helper functions for querying gdb.'''
- import logging
- import os
- import re
- import tempfile
- GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
- def _GdbOutputToFileLine(output_line):
- ''' Parse the gdb output line, return a pair (file, line num) '''
- match = GDB_LINE_RE.match(output_line)
- if match:
- return match.groups()[1], match.groups()[0]
- else:
- return None
- def ResolveAddressesWithinABinary(binary_name, load_address, address_list):
- ''' For each address, return a pair (file, line num) '''
- commands = tempfile.NamedTemporaryFile()
- commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address))
- for addr in address_list:
- commands.write('info line *%s\n' % addr)
- commands.write('quit\n')
- commands.flush()
- gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name
- gdb_pipe = os.popen(gdb_commandline)
- result = gdb_pipe.readlines()
- address_count = 0
- ret = {}
- for line in result:
- if line.startswith('Line'):
- ret[address_list[address_count]] = _GdbOutputToFileLine(line)
- address_count += 1
- if line.startswith('No line'):
- ret[address_list[address_count]] = (None, None)
- address_count += 1
- gdb_pipe.close()
- commands.close()
- return ret
- class AddressTable(object):
- ''' Object to do batched line number lookup. '''
- def __init__(self):
- self._load_addresses = {}
- self._binaries = {}
- self._all_resolved = False
- def AddBinaryAt(self, binary, load_address):
- ''' Register a new shared library or executable. '''
- self._load_addresses[binary] = load_address
- def Add(self, binary, address):
- ''' Register a lookup request. '''
- if binary == '':
- logging.warn('adding address %s in empty binary?' % address)
- if binary in self._binaries:
- self._binaries[binary].append(address)
- else:
- self._binaries[binary] = [address]
- self._all_resolved = False
- def ResolveAll(self):
- ''' Carry out all lookup requests. '''
- self._translation = {}
- for binary in self._binaries.keys():
- if binary != '' and binary in self._load_addresses:
- load_address = self._load_addresses[binary]
- addr = ResolveAddressesWithinABinary(
- binary, load_address, self._binaries[binary])
- self._translation[binary] = addr
- self._all_resolved = True
- def GetFileLine(self, binary, addr):
- ''' Get the (filename, linenum) result of a previously-registered lookup
- request.
- '''
- if self._all_resolved:
- if binary in self._translation:
- if addr in self._translation[binary]:
- return self._translation[binary][addr]
- return (None, None)
|