tools/rb/fix_stack_using_bpsyms.py

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 #!/usr/bin/env python
michael@0 2
michael@0 3 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6
michael@0 7 from __future__ import with_statement
michael@0 8
michael@0 9 import sys
michael@0 10 import os
michael@0 11 import re
michael@0 12 import bisect
michael@0 13
michael@0 14 def prettyFileName(name):
michael@0 15 if name.startswith("../") or name.startswith("..\\"):
michael@0 16 # dom_quickstubs.cpp and many .h files show up with relative paths that are useless
michael@0 17 # and/or don't correspond to the layout of the source tree.
michael@0 18 return os.path.basename(name) + ":"
michael@0 19 elif name.startswith("hg:"):
michael@0 20 bits = name.split(":")
michael@0 21 if len(bits) == 4:
michael@0 22 (junk, repo, path, rev) = bits
michael@0 23 # We could construct an hgweb URL with /file/ or /annotate/, like this:
michael@0 24 # return "http://%s/annotate/%s/%s#l" % (repo, rev, path)
michael@0 25 return path + ":"
michael@0 26 return name + ":"
michael@0 27
michael@0 28 class SymbolFile:
michael@0 29 def __init__(self, fn):
michael@0 30 addrs = [] # list of addresses, which will be sorted once we're done initializing
michael@0 31 funcs = {} # hash: address --> (function name + possible file/line)
michael@0 32 files = {} # hash: filenum (string) --> prettified filename ready to have a line number appended
michael@0 33 with open(fn) as f:
michael@0 34 for line in f:
michael@0 35 line = line.rstrip()
michael@0 36 # http://code.google.com/p/google-breakpad/wiki/SymbolFiles
michael@0 37 if line.startswith("FUNC "):
michael@0 38 # FUNC <address> <size> <stack_param_size> <name>
michael@0 39 (junk, rva, size, ss, name) = line.split(None, 4)
michael@0 40 rva = int(rva,16)
michael@0 41 funcs[rva] = name
michael@0 42 addrs.append(rva)
michael@0 43 lastFuncName = name
michael@0 44 elif line.startswith("PUBLIC "):
michael@0 45 # PUBLIC <address> <stack_param_size> <name>
michael@0 46 (junk, rva, ss, name) = line.split(None, 3)
michael@0 47 rva = int(rva,16)
michael@0 48 funcs[rva] = name
michael@0 49 addrs.append(rva)
michael@0 50 elif line.startswith("FILE "):
michael@0 51 # FILE <number> <name>
michael@0 52 (junk, filenum, name) = line.split(None, 2)
michael@0 53 files[filenum] = prettyFileName(name)
michael@0 54 elif line[0] in "0123456789abcdef":
michael@0 55 # This is one of the "line records" corresponding to the last FUNC record
michael@0 56 # <address> <size> <line> <filenum>
michael@0 57 (rva, size, line, filenum) = line.split(None)
michael@0 58 rva = int(rva,16)
michael@0 59 file = files[filenum]
michael@0 60 name = lastFuncName + " [" + file + line + "]"
michael@0 61 funcs[rva] = name
michael@0 62 addrs.append(rva)
michael@0 63 # skip everything else
michael@0 64 #print "Loaded %d functions from symbol file %s" % (len(funcs), os.path.basename(fn))
michael@0 65 self.addrs = sorted(addrs)
michael@0 66 self.funcs = funcs
michael@0 67
michael@0 68 def addrToSymbol(self, address):
michael@0 69 i = bisect.bisect(self.addrs, address) - 1
michael@0 70 if i > 0:
michael@0 71 #offset = address - self.addrs[i]
michael@0 72 return self.funcs[self.addrs[i]]
michael@0 73 else:
michael@0 74 return ""
michael@0 75
michael@0 76 def guessSymbolFile(fn, symbolsDir):
michael@0 77 """Guess a symbol file based on an object file's basename, ignoring the path and UUID."""
michael@0 78 fn = os.path.basename(fn)
michael@0 79 d1 = os.path.join(symbolsDir, fn)
michael@0 80 if not os.path.exists(d1):
michael@0 81 fn = fn + ".pdb"
michael@0 82 d1 = os.path.join(symbolsDir, fn)
michael@0 83 if not os.path.exists(d1):
michael@0 84 return None
michael@0 85 uuids = os.listdir(d1)
michael@0 86 if len(uuids) == 0:
michael@0 87 raise Exception("Missing symbol file for " + fn)
michael@0 88 if len(uuids) > 1:
michael@0 89 raise Exception("Ambiguous symbol file for " + fn)
michael@0 90 if fn.endswith(".pdb"):
michael@0 91 fn = fn[:-4]
michael@0 92 return os.path.join(d1, uuids[0], fn + ".sym")
michael@0 93
michael@0 94 parsedSymbolFiles = {}
michael@0 95 def getSymbolFile(file, symbolsDir):
michael@0 96 p = None
michael@0 97 if not file in parsedSymbolFiles:
michael@0 98 symfile = guessSymbolFile(file, symbolsDir)
michael@0 99 if symfile:
michael@0 100 p = SymbolFile(symfile)
michael@0 101 else:
michael@0 102 p = None
michael@0 103 parsedSymbolFiles[file] = p
michael@0 104 else:
michael@0 105 p = parsedSymbolFiles[file]
michael@0 106 return p
michael@0 107
michael@0 108 def addressToSymbol(file, address, symbolsDir):
michael@0 109 p = getSymbolFile(file, symbolsDir)
michael@0 110 if p:
michael@0 111 return p.addrToSymbol(address)
michael@0 112 else:
michael@0 113 return ""
michael@0 114
michael@0 115 line_re = re.compile("^(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,16})\](.*)$")
michael@0 116 balance_tree_re = re.compile("^([ \|0-9-]*)")
michael@0 117
michael@0 118 def fixSymbols(line, symbolsDir):
michael@0 119 result = line_re.match(line)
michael@0 120 if result is not None:
michael@0 121 # before allows preservation of balance trees
michael@0 122 # after allows preservation of counts
michael@0 123 (before, file, address, after) = result.groups()
michael@0 124 address = int(address, 16)
michael@0 125 # throw away the bad symbol, but keep balance tree structure
michael@0 126 before = balance_tree_re.match(before).groups()[0]
michael@0 127 symbol = addressToSymbol(file, address, symbolsDir)
michael@0 128 if not symbol:
michael@0 129 symbol = "%s + 0x%x" % (os.path.basename(file), address)
michael@0 130 return before + symbol + after + "\n"
michael@0 131 else:
michael@0 132 return line
michael@0 133
michael@0 134 if __name__ == "__main__":
michael@0 135 symbolsDir = sys.argv[1]
michael@0 136 for line in iter(sys.stdin.readline, ''):
michael@0 137 print fixSymbols(line, symbolsDir),

mercurial