~ubuntu-branches/ubuntu/trusty/enigmail/trusty-security

« back to all changes in this revision

Viewing changes to tools/rb/fix_stack_using_bpsyms.py

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2011-08-12 12:25:06 UTC
  • mfrom: (0.12.4 upstream)
  • Revision ID: package-import@ubuntu.com-20110812122506-zko6c7zfexvyg71q
Tags: 2:1.2.1-0ubuntu1
* New upstream release
* Drop fix_install_rdf_xml_errors.diff - fixed upstream
* Refresh port_to_latest_thunderbird.diff
* Add a proper get-orig-source target which pulls the build system from
  lp:~mozillateam/mozilla-build-system/beta, now that we don't have the old
  build-system.tar.gz from xulrunner

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
 
3
 
# ***** BEGIN LICENSE BLOCK *****
4
 
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
 
#
6
 
# The contents of this file are subject to the Mozilla Public License Version
7
 
# 1.1 (the "License"); you may not use this file except in compliance with
8
 
# the License. You may obtain a copy of the License at
9
 
# http://www.mozilla.org/MPL/
10
 
#
11
 
# Software distributed under the License is distributed on an "AS IS" basis,
12
 
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
 
# for the specific language governing rights and limitations under the
14
 
# License.
15
 
#
16
 
# The Original Code is fix_stack_using_bpsyms.py.
17
 
#
18
 
# The Initial Developer of the Original Code is the Mozilla Foundation.
19
 
# Portions created by the Initial Developer are Copyright (C) 2010
20
 
# the Initial Developer. All Rights Reserved.
21
 
#
22
 
# Contributor(s):
23
 
#   Jesse Ruderman <jruderman@gmail.com>
24
 
#   L. David Baron <dbaron@dbaron.org>
25
 
#   Ted Mielczarek <ted.mielczarek@gmail.com>
26
 
#
27
 
# Alternatively, the contents of this file may be used under the terms of
28
 
# either the GNU General Public License Version 2 or later (the "GPL"), or
29
 
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
 
# in which case the provisions of the GPL or the LGPL are applicable instead
31
 
# of those above. If you wish to allow use of your version of this file only
32
 
# under the terms of either the GPL or the LGPL, and not to allow others to
33
 
# use your version of this file under the terms of the MPL, indicate your
34
 
# decision by deleting the provisions above and replace them with the notice
35
 
# and other provisions required by the GPL or the LGPL. If you do not delete
36
 
# the provisions above, a recipient may use your version of this file under
37
 
# the terms of any one of the MPL, the GPL or the LGPL.
38
 
#
39
 
# ***** END LICENSE BLOCK *****
40
 
 
41
 
from __future__ import with_statement
42
 
 
43
 
import sys
44
 
import os
45
 
import re
46
 
import bisect
47
 
 
48
 
def prettyFileName(name):
49
 
  if name.startswith("../") or name.startswith("..\\"):
50
 
    # dom_quickstubs.cpp and many .h files show up with relative paths that are useless
51
 
    # and/or don't correspond to the layout of the source tree.
52
 
    return os.path.basename(name) + ":"
53
 
  elif name.startswith("hg:"):
54
 
    (junk, repo, path, rev) = name.split(":")
55
 
    # We could construct an hgweb URL with /file/ or /annotate/, like this:
56
 
    # return "http://%s/annotate/%s/%s#l" % (repo, rev, path)
57
 
    return path  + ":"
58
 
  return name  + ":"
59
 
 
60
 
class readSymbolFile:
61
 
  def __init__(self, fn):
62
 
    addrs = [] # list of addresses, which will be sorted once we're done initializing
63
 
    funcs = {} # hash: address --> (function name + possible file/line)
64
 
    files = {} # hash: filenum (string) --> prettified filename ready to have a line number appended
65
 
    with open(fn) as f:
66
 
      for line in f:
67
 
        line = line.rstrip()
68
 
        # http://code.google.com/p/google-breakpad/wiki/SymbolFiles
69
 
        if line.startswith("FUNC "):
70
 
          # FUNC <address> <size> <stack_param_size> <name>
71
 
          (junk, rva, size, ss, name) = line.split(None, 4)
72
 
          rva = int(rva,16)
73
 
          funcs[rva] = name
74
 
          addrs.append(rva)
75
 
          lastFuncName = name
76
 
        elif line.startswith("PUBLIC "):
77
 
          # PUBLIC <address> <stack_param_size> <name>
78
 
          (junk, rva, ss, name) = line.split(None, 3)
79
 
          rva = int(rva,16)
80
 
          funcs[rva] = name
81
 
          addrs.append(rva)
82
 
        elif line.startswith("FILE "):
83
 
          # FILE <number> <name>
84
 
          (junk, filenum, name) = line.split(None, 2)
85
 
          files[filenum] = prettyFileName(name)
86
 
        elif line[0] in "0123456789abcdef":
87
 
          # This is one of the "line records" corresponding to the last FUNC record
88
 
          # <address> <size> <line> <filenum>
89
 
          (rva, size, line, filenum) = line.split(None)
90
 
          rva = int(rva,16)
91
 
          file = files[filenum]
92
 
          name = lastFuncName + " [" + file + line + "]"
93
 
          funcs[rva] = name
94
 
          addrs.append(rva)
95
 
        # skip everything else
96
 
    #print "Loaded %d functions from symbol file %s" % (len(funcs), os.path.basename(fn))
97
 
    self.addrs = sorted(addrs)
98
 
    self.funcs = funcs
99
 
  def addrToSymbol(self, address):
100
 
    i = bisect.bisect(self.addrs, address) - 1
101
 
    if i > 0:
102
 
      #offset = address - self.addrs[i]
103
 
      return self.funcs[self.addrs[i]]
104
 
    else:
105
 
      return ""
106
 
 
107
 
 
108
 
def guessSymbolFile(fn, symbolsDir):
109
 
  """Guess a symbol file based on an object file's basename, ignoring the path and UUID."""
110
 
  fn = os.path.basename(fn)
111
 
  d1 = os.path.join(symbolsDir, fn)
112
 
  if not os.path.exists(d1):
113
 
    return None
114
 
  uuids = os.listdir(d1)
115
 
  if len(uuids) == 0:
116
 
    raise Exception("Missing symbol file for " + fn)
117
 
  if len(uuids) > 1:
118
 
    raise Exception("Ambiguous symbol file for " + fn)
119
 
  return os.path.join(d1, uuids[0], fn + ".sym")
120
 
 
121
 
parsedSymbolFiles = {}
122
 
def addressToSymbol(file, address, symbolsDir):
123
 
  p = None
124
 
  if not file in parsedSymbolFiles:
125
 
    symfile = guessSymbolFile(file, symbolsDir)
126
 
    if symfile:
127
 
      p = readSymbolFile(symfile)
128
 
    else:
129
 
      p = None
130
 
    parsedSymbolFiles[file] = p
131
 
  else:
132
 
    p = parsedSymbolFiles[file]
133
 
  if p:
134
 
    return p.addrToSymbol(address)
135
 
  else:
136
 
    return ""
137
 
 
138
 
line_re = re.compile("^(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,8})\](.*)$")
139
 
balance_tree_re = re.compile("^([ \|0-9-]*)")
140
 
 
141
 
def fixSymbols(line, symbolsDir):
142
 
  result = line_re.match(line)
143
 
  if result is not None:
144
 
    # before allows preservation of balance trees
145
 
    # after allows preservation of counts
146
 
    (before, file, address, after) = result.groups()
147
 
    address = int(address, 16)
148
 
    # throw away the bad symbol, but keep balance tree structure
149
 
    before = balance_tree_re.match(before).groups()[0]
150
 
    symbol = addressToSymbol(file, address, symbolsDir)
151
 
    if not symbol:
152
 
      symbol = "%s + 0x%x" % (os.path.basename(file), address)
153
 
    return before + symbol + after + "\n"
154
 
  else:
155
 
      return line
156
 
 
157
 
if __name__ == "__main__":
158
 
  symbolsDir = sys.argv[1]
159
 
  for line in iter(sys.stdin.readline, ''):
160
 
    print fixSymbols(line, symbolsDir),