Bug 1499907 - Add a `jsonEscape` argument to `fixSymbols`. r=erahm
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 21 Nov 2018 10:28:00 +1100
changeset 504042 fee6e5895b63477ac789aa50db43e6912e30106d
parent 504041 e92b86330728c5e78343d092d074762c34423540
child 504043 ad8114bf526cfa7c4e878bc6cb48dc582dc3363d
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1499907
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1499907 - Add a `jsonEscape` argument to `fixSymbols`. r=erahm So that dmd.py isn't broken by function names that, after stack fixing, contain escape-worthy chars such as " and /.
memory/replace/dmd/dmd.py
tools/rb/fix_linux_stack.py
tools/rb/fix_macosx_stack.py
tools/rb/fix_stack_using_bpsyms.py
--- a/memory/replace/dmd/dmd.py
+++ b/memory/replace/dmd/dmd.py
@@ -214,25 +214,29 @@ def fixStackTraces(inputFilename, isZipp
     # script is installed as a symlink.
     sys.path.append(os.path.dirname(__file__))
 
     bpsyms = os.environ.get('BREAKPAD_SYMBOLS_PATH', None)
     sysname = platform.system()
     if bpsyms and os.path.exists(bpsyms):
         import fix_stack_using_bpsyms as fixModule
 
-        def fix(line): return fixModule.fixSymbols(line, bpsyms)
+        def fix(line):
+            return fixModule.fixSymbols(line, bpsyms, jsonEscape=True)
+
     elif sysname == 'Linux':
         import fix_linux_stack as fixModule
 
-        def fix(line): return fixModule.fixSymbols(line)
+        def fix(line): return fixModule.fixSymbols(line, jsonEscape=True)
+
     elif sysname == 'Darwin':
         import fix_macosx_stack as fixModule
 
-        def fix(line): return fixModule.fixSymbols(line)
+        def fix(line): return fixModule.fixSymbols(line, jsonEscape=True)
+
     else:
         fix = None  # there is no fix script for Windows
 
     if fix:
         # Fix stacks, writing output to a temporary file, and then
         # overwrite the original file.
         tmpFile = tempfile.NamedTemporaryFile(delete=False)
 
--- a/tools/rb/fix_linux_stack.py
+++ b/tools/rb/fix_linux_stack.py
@@ -3,20 +3,21 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This script uses addr2line (part of binutils) to post-process the entries
 # produced by NS_FormatCodeAddress(), which on Linux often lack a function
 # name, a file name and a line number.
 
+import json
+import os
+import re
 import subprocess
 import sys
-import re
-import os
 from StringIO import StringIO
 
 objdump_section_re = re.compile(
     "^ [0-9a-f]* ([0-9a-f ]{8}) ([0-9a-f ]{8}) ([0-9a-f ]{8}) ([0-9a-f ]{8}).*")
 
 
 def elf_section(file, section):
     """
@@ -279,30 +280,34 @@ def addressToSymbol(file, address):
     cache[address] = result
     return result
 
 
 # Matches lines produced by NS_FormatCodeAddress().
 line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
 
 
-def fixSymbols(line):
+def fixSymbols(line, jsonEscape=False):
     result = line_re.match(line)
     if result is not None:
         (before, fn, file, address, after) = result.groups()
 
         if os.path.exists(file) and os.path.isfile(file):
             (name, fileline) = addressToSymbol(file, address)
 
             # If addr2line gave us something useless, keep what we had before.
             if name == "??":
                 name = fn
             if fileline == "??:0" or fileline == "??:?":
                 fileline = file
 
+            if jsonEscape:
+                name = json.dumps(name)[1:-1]         # [1:-1] strips the quotes
+                fileline = json.dumps(fileline)[1:-1]
+
             nl = '\n' if line[-1] == '\n' else ''
             return "%s%s (%s)%s%s" % (before, name, fileline, after, nl)
         else:
             sys.stderr.write("Warning: File \"" + file + "\" does not exist.\n")
             return line
     else:
         return line
 
--- a/tools/rb/fix_macosx_stack.py
+++ b/tools/rb/fix_macosx_stack.py
@@ -3,21 +3,22 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This script uses |atos| to post-process the entries produced by
 # NS_FormatCodeAddress(), which on Mac often lack a file name and a line
 # number.
 
+import json
+import os
+import pty
+import re
 import subprocess
 import sys
-import re
-import os
-import pty
 import termios
 
 
 class unbufferedLineConverter:
     """
     Wrap a child process that responds to each line of input with one line of
     output.  Uses pty to trick the child into providing unbuffered output.
     """
@@ -108,17 +109,17 @@ def cxxfilt(sym):
     return cxxfilt_proc.stdout.readline().rstrip("\n")
 
 
 # Matches lines produced by NS_FormatCodeAddress().
 line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
 atos_name_re = re.compile("^(.+) \(in ([^)]+)\) \((.+)\)$")
 
 
-def fixSymbols(line):
+def fixSymbols(line, jsonEscape=False):
     result = line_re.match(line)
     if result is not None:
         (before, fn, file, address, after) = result.groups()
         address = int(address, 16)
 
         if os.path.exists(file) and os.path.isfile(file):
             address += address_adjustment(file)
             info = addressToSymbol(file, address)
@@ -132,16 +133,19 @@ def fixSymbols(line):
                 # Print the first two forms as-is, and transform the third
                 (name, library, fileline) = name_result.groups()
                 # atos demangles, but occasionally it fails.  cxxfilt can mop
                 # up the remaining cases(!), which will begin with '_Z'.
                 if (name.startswith("_Z")):
                     name = cxxfilt(name)
                 info = "%s (%s, in %s)" % (name, fileline, library)
 
+            if jsonEscape:
+                info = json.dumps(info)[1:-1]   # [1:-1] strips the quotes
+
             nl = '\n' if line[-1] == '\n' else ''
             return before + info + after + nl
         else:
             sys.stderr.write("Warning: File \"" + file + "\" does not exist.\n")
             return line
     else:
         return line
 
--- a/tools/rb/fix_stack_using_bpsyms.py
+++ b/tools/rb/fix_stack_using_bpsyms.py
@@ -7,16 +7,17 @@
 # This script uses breakpad symbols to post-process the entries produced by
 # NS_FormatCodeAddress(), which on TBPL builds often lack a file name and a
 # line number (and on Linux even the symbol is often bad).
 
 from __future__ import with_statement
 
 import bisect
 import collections
+import json
 import os
 import re
 import subprocess
 import sys
 
 here = os.path.dirname(__file__)
 FunctionSymbol = collections.namedtuple('FunctionSymbol', ['name', 'size'])
 
@@ -182,24 +183,26 @@ def addressToSymbol(file, address, symbo
     else:
         return ""
 
 
 # Matches lines produced by NS_FormatCodeAddress().
 line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
 
 
-def fixSymbols(line, symbolsDir):
+def fixSymbols(line, symbolsDir, jsonEscape=False):
     result = line_re.match(line)
     if result is not None:
         (before, fn, file, address, after) = result.groups()
         address = int(address, 16)
         symbol = addressToSymbol(file, address, symbolsDir)
         if not symbol:
             symbol = "%s + 0x%x" % (os.path.basename(file), address)
+        if jsonEscape:
+            symbol = json.dumps(symbol)[1:-1]   # [1:-1] strips the quotes
         return before + symbol + after + "\n"
     else:
         return line
 
 
 if __name__ == "__main__":
     symbolsDir = sys.argv[1]
     for line in iter(sys.stdin.readline, ''):