15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 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)import bisect
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_ARGUMENT_TYPE_PATTERN = re.compile('\([^()]*\)(\s*const)?')
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_TEMPLATE_ARGUMENT_PATTERN = re.compile('<[^<>]*>')
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_LEADING_TYPE_PATTERN = re.compile('^.*\s+(\w+::)')
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_READELF_SECTION_HEADER_PATTER = re.compile(
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '^\s*\[\s*(Nr|\d+)\]\s+(|\S+)\s+([A-Z_]+)\s+([0-9a-f]+)\s+'
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9]+)\s+([WAXMSILGxOop]*)\s+'
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '([0-9]+)\s+([0-9]+)\s+([0-9]+)')
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ParsingException(Exception):
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return repr(self.args[0])
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AddressMapping(object):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._symbol_map = {}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def append(self, start, entry):
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._symbol_map[start] = entry
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def find(self, address):
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._symbol_map.get(address)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RangeAddressMapping(AddressMapping):
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    super(RangeAddressMapping, self).__init__()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._sorted_start_list = []
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._is_sorted = True
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def append(self, start, entry):
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._sorted_start_list:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self._sorted_start_list[-1] > start:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._is_sorted = False
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif self._sorted_start_list[-1] == start:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._sorted_start_list.append(start)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._symbol_map[start] = entry
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def find(self, address):
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if not self._sorted_start_list:
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return None
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not self._is_sorted:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._sorted_start_list.sort()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._is_sorted = True
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found_index = bisect.bisect_left(self._sorted_start_list, address)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found_start_address = self._sorted_start_list[found_index - 1]
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._symbol_map[found_start_address]
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Procedure(object):
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A class for a procedure symbol and an address range for the symbol."""
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, start, end, name):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.start = start
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.end = end
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.name = name
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (self.start == other.start and
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.end == other.end and
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.name == other.name)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __ne__(self, other):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not self.__eq__(other)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%x-%x: %s' % (self.start, self.end, self.name)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ElfSection(object):
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A class for an elf section header."""
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self, number, name, stype, address, offset, size, es, flg, lk, inf, al):
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.number = number
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.name = name
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stype = stype
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.address = address
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.offset = offset
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.size = size
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.es = es
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.flg = flg
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.lk = lk
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.inf = inf
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.al = al
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __eq__(self, other):
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (self.number == other.number and
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.name == other.name and
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.stype == other.stype and
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.address == other.address and
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.offset == other.offset and
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.size == other.size and
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.es == other.es and
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.flg == other.flg and
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.lk == other.lk and
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.inf == other.inf and
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.al == other.al)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __ne__(self, other):
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not self.__eq__(other)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%x+%x(%x) %s' % (self.address, self.size, self.offset, self.name)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StaticSymbolsInFile(object):
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Represents static symbol information in a binary file."""
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, my_name):
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.my_name = my_name
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._elf_sections = []
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._procedures = RangeAddressMapping()
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._sourcefiles = RangeAddressMapping()
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._typeinfos = AddressMapping()
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _append_elf_section(self, elf_section):
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._elf_sections.append(elf_section)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _append_procedure(self, start, procedure):
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._procedures.append(start, procedure)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def _append_sourcefile(self, start, sourcefile):
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._sourcefiles.append(start, sourcefile)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _append_typeinfo(self, start, typeinfo):
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._typeinfos.append(start, typeinfo)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _find_symbol_by_runtime_address(self, address, vma, target):
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not (vma.begin <= address < vma.end):
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return None
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if vma.name != self.my_name:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return None
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_offset = address - (vma.begin - vma.offset)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elf_address = None
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for section in self._elf_sections:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if section.offset <= file_offset < (section.offset + section.size):
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elf_address = section.address + file_offset - section.offset
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not elf_address:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return None
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return target.find(elf_address)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def find_procedure_by_runtime_address(self, address, vma):
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._find_symbol_by_runtime_address(address, vma, self._procedures)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def find_sourcefile_by_runtime_address(self, address, vma):
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return self._find_symbol_by_runtime_address(address, vma, self._sourcefiles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def find_typeinfo_by_runtime_address(self, address, vma):
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._find_symbol_by_runtime_address(address, vma, self._typeinfos)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def load_readelf_ew(self, f):
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found_header = False
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in f:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if line.rstrip() == 'Section Headers:':
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_header = True
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not found_header:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return None
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in f:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line = line.rstrip()
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      matched = _READELF_SECTION_HEADER_PATTER.match(line)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if matched:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._append_elf_section(ElfSection(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int(matched.group(1), 10), # number
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(2), # name
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(3), # stype
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int(matched.group(4), 16), # address
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int(matched.group(5), 16), # offset
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int(matched.group(6), 16), # size
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(7), # es
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(8), # flg
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(9), # lk
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(10), # inf
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            matched.group(11) # al
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ))
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if line in ('Key to Flags:', 'Program Headers:'):
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def load_readelf_debug_decodedline_file(self, input_file):
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for line in input_file:
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      splitted = line.rstrip().split(None, 2)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._append_sourcefile(int(splitted[0], 16), splitted[1])
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @staticmethod
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _parse_nm_bsd_line(line):
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if line[8] == ' ':
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return line[0:8], line[9], line[11:]
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif line[16] == ' ':
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return line[0:16], line[17], line[19:]
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise ParsingException('Invalid nm output.')
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @staticmethod
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _get_short_function_name(function):
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while True:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function, number = _ARGUMENT_TYPE_PATTERN.subn('', function)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not number:
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while True:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function, number = _TEMPLATE_ARGUMENT_PATTERN.subn('', function)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not number:
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return _LEADING_TYPE_PATTERN.sub('\g<1>', function)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def load_nm_bsd(self, f, mangled=False):
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_start = 0
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    routine = ''
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in f:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line = line.rstrip()
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sym_value, sym_type, sym_name = self._parse_nm_bsd_line(line)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if sym_value[0] == ' ':
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_val = int(sym_value, 16)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sym_type in ('r', 'R', 'D', 'U', 'd', 'V') and
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (not mangled and sym_name.startswith('typeinfo'))):
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._append_typeinfo(start_val, sym_name)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # It's possible for two symbols to share the same address, if
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # one is a zero-length variable (like __start_google_malloc) or
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # one symbol is a weak alias to another (like __libc_malloc).
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # In such cases, we want to ignore all values except for the
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # actual symbol, which in nm-speak has type "T".  The logic
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # below does this, though it's a bit tricky: what happens when
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # we have a series of lines with the same address, is the first
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # one gets queued up to be processed.  However, it won't
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # *actually* be processed until later, when we read a line with
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # a different address.  That means that as long as we're reading
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # lines with the same address, we have a chance to replace that
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # item in the queue, which we do whenever we see a 'T' entry --
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # that is, a line with type 'T'.  If we never see a 'T' entry,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # we'll just go ahead and process the first entry (which never
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # got touched in the queue), and ignore the others.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if start_val == last_start and (sym_type == 't' or sym_type == 'T'):
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # We are the 'T' symbol at this address, replace previous symbol.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        routine = sym_name
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif start_val == last_start:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # We're not the 'T' symbol at this address, so ignore us.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Tag this routine with the starting address in case the image
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # has multiple occurrences of this routine.  We use a syntax
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # that resembles template paramters that are automatically
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # stripped out by ShortFunctionName()
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sym_name += "<%016x>" % start_val
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not mangled:
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        routine = self._get_short_function_name(routine)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._append_procedure(
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          last_start, Procedure(last_start, start_val, routine))
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_start = start_val
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      routine = sym_name
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not mangled:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      routine = self._get_short_function_name(routine)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._append_procedure(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_start, Procedure(last_start, last_start, routine))
278