15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)''' A bunch of helper functions for querying gdb.''' 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*') 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _GdbOutputToFileLine(output_line): 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Parse the gdb output line, return a pair (file, line num) ''' 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match = GDB_LINE_RE.match(output_line) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if match: 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return match.groups()[1], match.groups()[0] 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ResolveAddressesWithinABinary(binary_name, load_address, address_list): 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' For each address, return a pair (file, line num) ''' 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands = tempfile.NamedTemporaryFile() 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address)) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for addr in address_list: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands.write('info line *%s\n' % addr) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands.write('quit\n') 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands.flush() 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdb_pipe = os.popen(gdb_commandline) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = gdb_pipe.readlines() 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_count = 0 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = {} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line in result: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if line.startswith('Line'): 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret[address_list[address_count]] = _GdbOutputToFileLine(line) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_count += 1 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if line.startswith('No line'): 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret[address_list[address_count]] = (None, None) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_count += 1 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdb_pipe.close() 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands.close() 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AddressTable(object): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Object to do batched line number lookup. ''' 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._load_addresses = {} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._binaries = {} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._all_resolved = False 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def AddBinaryAt(self, binary, load_address): 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Register a new shared library or executable. ''' 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._load_addresses[binary] = load_address 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Add(self, binary, address): 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Register a lookup request. ''' 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if binary == '': 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn('adding address %s in empty binary?' % address) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if binary in self._binaries: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._binaries[binary].append(address) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._binaries[binary] = [address] 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._all_resolved = False 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ResolveAll(self): 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Carry out all lookup requests. ''' 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._translation = {} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for binary in self._binaries.keys(): 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if binary != '' and binary in self._load_addresses: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_address = self._load_addresses[binary] 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr = ResolveAddressesWithinABinary( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) binary, load_address, self._binaries[binary]) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._translation[binary] = addr 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._all_resolved = True 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetFileLine(self, binary, addr): 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Get the (filename, linenum) result of a previously-registered lookup 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._all_resolved: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if binary in self._translation: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if addr in self._translation[binary]: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self._translation[binary][addr] 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (None, None) 88