diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/crashreporter/google-breakpad/src/tools/python | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/tools/python')
3 files changed, 509 insertions, 0 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py b/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py new file mode 100755 index 0000000000..b456285431 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +# Copyright 2016 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Convert gclient's DEPS file to repo's manifest xml file.""" + +from __future__ import print_function + +import argparse +import os +import sys + + +REMOTES = { + 'chromium': 'https://chromium.googlesource.com/', + 'github': 'https://github.com/', +} +REVIEWS = { + 'chromium': 'https://chromium-review.googlesource.com', +} + +MANIFEST_HEAD = """<?xml version='1.0' encoding='UTF-8'?> +<!-- AUTOGENERATED BY %(prog)s; DO NOT EDIT --> +<manifest> + + <default revision='refs/heads/master' + remote='chromium' + sync-c='true' + sync-j='8' /> +""" + +MANIFEST_REMOTE = """ + <remote name='%(name)s' + fetch='%(fetch)s' + review='%(review)s' /> +""" + +MANIFEST_PROJECT = """ + <project path='%(path)s' + name='%(name)s' + revision='%(revision)s' + remote='%(remote)s' /> +""" + +MANIFEST_TAIL = """ +</manifest> +""" + + +def ConvertDepsToManifest(deps, manifest): + """Convert the |deps| file to the |manifest|.""" + # Load the DEPS file data. + ctx = {} + execfile(deps, ctx) + + new_contents = '' + + # Write out the common header. + data = { + 'prog': os.path.basename(__file__), + } + new_contents += MANIFEST_HEAD % data + + # Write out the <remote> sections. + for name, fetch in REMOTES.items(): + data = { + 'name': name, + 'fetch': fetch, + 'review': REVIEWS.get(name, ''), + } + new_contents += MANIFEST_REMOTE % data + + # Write out the main repo itself. + data = { + 'path': 'src', + 'name': 'breakpad/breakpad', + 'revision': 'refs/heads/master', + 'remote': 'chromium', + } + new_contents += MANIFEST_PROJECT % data + + # Write out the <project> sections. + for path, url in ctx['deps'].items(): + for name, fetch in REMOTES.items(): + if url.startswith(fetch): + remote = name + break + else: + raise ValueError('Unknown DEPS remote: %s: %s' % (path, url)) + + # The DEPS url will look like: + # https://chromium.googlesource.com/external/gyp/@e8ab0833a42691cd2 + remote_path, rev = url.split('@') + remote_path = remote_path[len(fetch):] + + # If it's not a revision, assume it's a tag. Repo wants full ref names. + if len(rev) != 40: + rev = 'refs/tags/%s' % rev + + data = { + 'path': path, + 'name': remote_path, + 'revision': rev, + 'remote': remote, + } + new_contents += MANIFEST_PROJECT % data + + # Write out the common footer. + new_contents += MANIFEST_TAIL + + # See if the manifest has actually changed contents to avoid thrashing. + try: + old_contents = open(manifest).read() + except IOError: + # In case the file doesn't exist yet. + old_contents = '' + if old_contents != new_contents: + print('Updating %s due to changed %s' % (manifest, deps)) + with open(manifest, 'w') as fp: + fp.write(new_contents) + + +def GetParser(): + """Return a CLI parser.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('deps', + help='The DEPS file to convert') + parser.add_argument('manifest', + help='The manifest xml to generate') + return parser + + +def main(argv): + """The main func!""" + parser = GetParser() + opts = parser.parse_args(argv) + ConvertDepsToManifest(opts.deps, opts.manifest) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py b/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py new file mode 100644 index 0000000000..abddf7893e --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# Copyright (c) 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Normalizes and de-duplicates paths within Breakpad symbol files. + +When using DWARF for storing debug symbols, some file information will be +stored relative to the current working directory of the current compilation +unit, and may be further relativized based upon how the file was #included. + +This helper can be used to parse the Breakpad symbol file generated from such +DWARF files and normalize and de-duplicate the FILE records found within, +updating any references to the FILE records in the other record types. +""" + +import macpath +import ntpath +import optparse +import os +import posixpath +import sys + +class BreakpadParseError(Exception): + """Unsupported Breakpad symbol record exception class.""" + pass + +class SymbolFileParser(object): + """Parser for Breakpad symbol files. + + The format of these files is documented at + https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md + """ + + def __init__(self, input_stream, output_stream, ignored_prefixes=None, + path_handler=os.path): + """Inits a SymbolFileParser to read symbol records from |input_stream| and + write the processed output to |output_stream|. + + |ignored_prefixes| contains a list of optional path prefixes that + should be stripped from the final, normalized path outputs. + + For example, if the Breakpad symbol file had all paths starting with a + common prefix, such as: + FILE 1 /b/build/src/foo.cc + FILE 2 /b/build/src/bar.cc + Then adding "/b/build/src" as an ignored prefix would result in an output + file that contained: + FILE 1 foo.cc + FILE 2 bar.cc + + Note that |ignored_prefixes| does not necessarily contain file system + paths, as the contents of the DWARF DW_AT_comp_dir attribute is dependent + upon the host system and compiler, and may contain additional information + such as hostname or compiler version. + """ + + self.unique_files = {} + self.duplicate_files = {} + self.input_stream = input_stream + self.output_stream = output_stream + self.ignored_prefixes = ignored_prefixes or [] + self.path_handler = path_handler + + def Process(self): + """Processes the Breakpad symbol file.""" + for line in self.input_stream: + parsed = self._ParseRecord(line.rstrip()) + if parsed: + self.output_stream.write(parsed + '\n') + + def _ParseRecord(self, record): + """Parses a single Breakpad symbol record - a single line from the symbol + file. + + Returns: + The modified string to write to the output file, or None if no line + should be written. + """ + record_type = record.partition(' ')[0] + if record_type == 'FILE': + return self._ParseFileRecord(record) + elif self._IsLineRecord(record_type): + return self._ParseLineRecord(record) + else: + # Simply pass the record through unaltered. + return record + + def _NormalizePath(self, path): + """Normalizes a file path to its canonical form. + + As this may not execute on the machine or file system originally + responsible for compilation, it may be necessary to further correct paths + for symlinks, junctions, or other such file system indirections. + + Returns: + A unique, canonical representation for the the file path. + """ + return self.path_handler.normpath(path) + + def _AdjustPath(self, path): + """Adjusts the supplied path after performing path de-duplication. + + This may be used to perform secondary adjustments, such as removing a + common prefix, such as "/D/build", or replacing the file system path with + information from the version control system. + + Returns: + The actual path to use when writing the FILE record. + """ + return path[len(filter(path.startswith, + self.ignored_prefixes + [''])[0]):] + + def _ParseFileRecord(self, file_record): + """Parses and corrects a FILE record.""" + file_info = file_record[5:].split(' ', 3) + if len(file_info) > 2: + raise BreakpadParseError('Unsupported FILE record: ' + file_record) + file_index = int(file_info[0]) + file_name = self._NormalizePath(file_info[1]) + existing_file_index = self.unique_files.get(file_name) + if existing_file_index is None: + self.unique_files[file_name] = file_index + file_info[1] = self._AdjustPath(file_name) + return 'FILE ' + ' '.join(file_info) + else: + self.duplicate_files[file_index] = existing_file_index + return None + + def _IsLineRecord(self, record_type): + """Determines if the current record type is a Line record""" + try: + line = int(record_type, 16) + except (ValueError, TypeError): + return False + return True + + def _ParseLineRecord(self, line_record): + """Parses and corrects a Line record.""" + line_info = line_record.split(' ', 5) + if len(line_info) > 4: + raise BreakpadParseError('Unsupported Line record: ' + line_record) + file_index = int(line_info[3]) + line_info[3] = str(self.duplicate_files.get(file_index, file_index)) + return ' '.join(line_info) + +def main(): + option_parser = optparse.OptionParser() + option_parser.add_option("-p", "--prefix", + action="append", dest="prefixes", type="string", + default=[], + help="A path prefix that should be removed from " + "all FILE lines. May be repeated to specify " + "multiple prefixes.") + option_parser.add_option("-t", "--path_type", + action="store", type="choice", dest="path_handler", + choices=['win32', 'posix'], + help="Indicates how file paths should be " + "interpreted. The default is to treat paths " + "the same as the OS running Python (eg: " + "os.path)") + options, args = option_parser.parse_args() + if args: + option_parser.error('Unknown argument: %s' % args) + + path_handler = { 'win32': ntpath, + 'posix': posixpath }.get(options.path_handler, os.path) + try: + symbol_parser = SymbolFileParser(sys.stdin, sys.stdout, options.prefixes, + path_handler) + symbol_parser.Process() + except BreakpadParseError, e: + print >> sys.stderr, 'Got an error while processing symbol file' + print >> sys.stderr, str(e) + return 1 + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py b/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py new file mode 100644 index 0000000000..b111f34983 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# Copyright (c) 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Unit tests for filter_syms.py""" + +import cStringIO +import ntpath +import os +import StringIO +import sys +import unittest + +ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(ROOT_DIR, '..')) + +# In root +import filter_syms + +class FilterSysmsTest(unittest.TestCase): + def assertParsed(self, input_data, ignored_prefixes, expected): + input_io = cStringIO.StringIO(input_data) + output_io = cStringIO.StringIO() + parser = filter_syms.SymbolFileParser(input_io, output_io, + ignored_prefixes, ntpath) + parser.Process() + self.assertEqual(output_io.getvalue(), expected) + + def testDuplicateFiles(self): + """Tests that duplicate files in FILE records are correctly removed and + that Line records are updated.""" + + INPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 foo/../file1_1.cc +FILE 2 bar/../file1_1.cc +FILE 3 baz/../file1_1.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 2 +1008 4 46 3 +100c 4 44 1 +""" + EXPECTED_OUTPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 file1_1.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 1 +1008 4 46 1 +100c 4 44 1 +""" + self.assertParsed(INPUT, [], EXPECTED_OUTPUT) + + def testIgnoredPrefix(self): + """Tests that prefixes in FILE records are correctly removed.""" + + INPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 /src/build/foo/../file1_1.cc +FILE 2 /src/build/bar/../file1_2.cc +FILE 3 /src/build/baz/../file1_2.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 2 +1008 4 46 3 +100c 4 44 1 +""" + EXPECTED_OUTPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 file1_1.cc +FILE 2 file1_2.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 2 +1008 4 46 2 +100c 4 44 1 +""" + IGNORED_PREFIXES = ['\\src\\build\\'] + self.assertParsed(INPUT, IGNORED_PREFIXES, EXPECTED_OUTPUT) + + def testIgnoredPrefixesDuplicateFiles(self): + """Tests that de-duplication of FILE records happens BEFORE prefixes + are removed.""" + + INPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 /src/build/foo/../file1_1.cc +FILE 2 /src/build/bar/../file1_2.cc +FILE 3 D:/src/build2/baz/../file1_2.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 2 +1008 4 46 3 +100c 4 44 1 +""" + EXPECTED_OUTPUT = \ +"""MODULE windows x86 111111111111111111111111111111111 module1.pdb +INFO CODE_ID FFFFFFFF module1.exe +FILE 1 file1_1.cc +FILE 2 file1_2.cc +FILE 3 file1_2.cc +FUNC 1000 c 0 Function1_1 +1000 8 45 2 +1008 4 46 3 +100c 4 44 1 +""" + IGNORED_PREFIXES = ['\\src\\build\\', 'D:\\src\\build2\\'] + self.assertParsed(INPUT, IGNORED_PREFIXES, EXPECTED_OUTPUT) + +if __name__ == '__main__': + unittest.main()
\ No newline at end of file |