mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 1216681
- Add a fileid utility to extract the breakpad GUID from object files for identification in fix_stack_using_bpsyms. r=ted
fix_stack_using_bpsyms.py locates a .sym file based on file name only, not uuid or full path, which causes a failure if a duplicate leaf file name is introduced. This patch introduces a small utility program on mac and linux to extract a breakpad guid from a shared library or executable to identify the correct symbol file when this ambiguity occurs. A subsequent commit implements this for windows.
This commit is contained in:
parent
9d97726f6c
commit
10b3355fe8
@ -20,6 +20,7 @@ libs::
|
||||
TEST_HARNESS_BINS := \
|
||||
xpcshell$(BIN_SUFFIX) \
|
||||
ssltunnel$(BIN_SUFFIX) \
|
||||
fileid$(BIN_SUFFIX) \
|
||||
certutil$(BIN_SUFFIX) \
|
||||
pk12util$(BIN_SUFFIX) \
|
||||
BadCertServer$(BIN_SUFFIX) \
|
||||
|
51
testing/tools/fileid/linux_fileid.cpp
Normal file
51
testing/tools/fileid/linux_fileid.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* 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/. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common/linux/file_id.h"
|
||||
|
||||
//TODO: move this somewhere common, this is copied from dump_symbols.cc
|
||||
// Format the Elf file identifier in IDENTIFIER as a UUID with the
|
||||
// dashes removed.
|
||||
void FormatIdentifier(unsigned char identifier[google_breakpad::kMDGUIDSize],
|
||||
char result_guid[40]) {
|
||||
char identifier_str[40];
|
||||
google_breakpad::FileID::ConvertIdentifierToString(
|
||||
identifier,
|
||||
identifier_str,
|
||||
sizeof(identifier_str));
|
||||
int bufpos = 0;
|
||||
for (int i = 0; identifier_str[i] != '\0'; ++i)
|
||||
if (identifier_str[i] != '-')
|
||||
result_guid[bufpos++] = identifier_str[i];
|
||||
// Add an extra "0" by the end. PDB files on Windows have an 'age'
|
||||
// number appended to the end of the file identifier; this isn't
|
||||
// really used or necessary on other platforms, but let's preserve
|
||||
// the pattern.
|
||||
result_guid[bufpos++] = '0';
|
||||
// And null terminate.
|
||||
result_guid[bufpos] = '\0';
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: fileid <elf file>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char identifier[google_breakpad::kMDGUIDSize];
|
||||
google_breakpad::FileID file_id(argv[1]);
|
||||
if (!file_id.ElfFileIdentifier(identifier)) {
|
||||
fprintf(stderr, "%s: unable to generate file identifier\n",
|
||||
argv[1]);
|
||||
return 1;
|
||||
}
|
||||
char result_guid[40];
|
||||
FormatIdentifier(identifier, result_guid);
|
||||
printf("%s\n", result_guid);
|
||||
return 0;
|
||||
}
|
52
testing/tools/fileid/mac_fileid.cpp
Normal file
52
testing/tools/fileid/mac_fileid.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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/. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/mac/arch_utilities.h"
|
||||
#include "common/mac/file_id.h"
|
||||
|
||||
//TODO: move this somewhere common, this is copied from dump_symbols.cc
|
||||
// Format the Mach-O identifier in IDENTIFIER as a UUID with the
|
||||
// dashes removed.
|
||||
std::string FormatIdentifier(unsigned char identifier[16])
|
||||
{
|
||||
char identifier_string[40];
|
||||
google_breakpad::FileID::ConvertIdentifierToString(identifier, identifier_string,
|
||||
sizeof(identifier_string));
|
||||
std::string compacted(identifier_string);
|
||||
for(size_t i = compacted.find('-'); i != std::string::npos;
|
||||
i = compacted.find('-', i))
|
||||
compacted.erase(i, 1);
|
||||
compacted += '0';
|
||||
return compacted;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: fileid <object file>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
unsigned char identifier[16];
|
||||
google_breakpad::FileID file_id(argv[1]);
|
||||
|
||||
// We should be able to use NXGetLocalArchInfo for this, but it returns
|
||||
// CPU_TYPE_X86 (which is the same as CPU_TYPE_I386) on x86_64 machines,
|
||||
// when our binary will typically have CPU_TYPE_X86_64 to match against.
|
||||
// So we hard code x86_64. In practice that's where we're running tests,
|
||||
// and that's what our debug binaries will contain.
|
||||
if (!file_id.MachoIdentifier(CPU_TYPE_X86_64, CPU_SUBTYPE_MULTIPLE,
|
||||
identifier)) {
|
||||
fprintf(stderr, "%s: unable to generate file identifier\n",
|
||||
argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s\n", FormatIdentifier(identifier).c_str());
|
||||
return 0;
|
||||
}
|
29
testing/tools/fileid/moz.build
Normal file
29
testing/tools/fileid/moz.build
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Linux':
|
||||
USE_LIBS += [
|
||||
'breakpad_linux_common_s',
|
||||
]
|
||||
SOURCES += ['linux_fileid.cpp']
|
||||
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
'breakpad_mac_common_s',
|
||||
]
|
||||
SOURCES += ['mac_fileid.cpp']
|
||||
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Linux' or CONFIG['OS_ARCH'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
'breakpad_common_s',
|
||||
'breakpad_logging',
|
||||
]
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src',
|
||||
]
|
||||
Program('fileid')
|
@ -173,6 +173,7 @@ if CONFIG['ENABLE_TESTS']:
|
||||
'/testing/mochitest',
|
||||
'/testing/xpcshell',
|
||||
'/testing/tools/screenshot',
|
||||
'/testing/tools/fileid',
|
||||
'/testing/profiles',
|
||||
'/testing/mozbase',
|
||||
'/testing/modules',
|
||||
|
@ -13,8 +13,11 @@ from __future__ import with_statement
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import bisect
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
|
||||
def prettyFileName(name):
|
||||
if name.startswith("../") or name.startswith("..\\"):
|
||||
# dom_quickstubs.cpp and many .h files show up with relative paths that are useless
|
||||
@ -77,9 +80,21 @@ class SymbolFile:
|
||||
else:
|
||||
return ""
|
||||
|
||||
def guessSymbolFile(fn, symbolsDir):
|
||||
def findIdForPath(path):
|
||||
"""Finds the breakpad id for the object file at the given path."""
|
||||
# We should always be packaged with a "fileid" executable.
|
||||
fileid_exe = os.path.join(here, 'fileid')
|
||||
if not os.path.isfile(fileid_exe):
|
||||
raise Exception("Could not find fileid executable in %s" % here)
|
||||
try:
|
||||
return subprocess.check_output([fileid_exe, path]).rstrip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise Exception("Error getting fileid for %s: %s" %
|
||||
(path, e.output))
|
||||
|
||||
def guessSymbolFile(full_path, symbolsDir):
|
||||
"""Guess a symbol file based on an object file's basename, ignoring the path and UUID."""
|
||||
fn = os.path.basename(fn)
|
||||
fn = os.path.basename(full_path)
|
||||
d1 = os.path.join(symbolsDir, fn)
|
||||
if not os.path.exists(d1):
|
||||
fn = fn + ".pdb"
|
||||
@ -90,10 +105,12 @@ def guessSymbolFile(fn, symbolsDir):
|
||||
if len(uuids) == 0:
|
||||
raise Exception("Missing symbol file for " + fn)
|
||||
if len(uuids) > 1:
|
||||
raise Exception("Ambiguous symbol file for " + fn)
|
||||
uuid = findIdForPath(full_path)
|
||||
else:
|
||||
uuid = uuids[0]
|
||||
if fn.endswith(".pdb"):
|
||||
fn = fn[:-4]
|
||||
return os.path.join(d1, uuids[0], fn + ".sym")
|
||||
return os.path.join(d1, uuid, fn + ".sym")
|
||||
|
||||
parsedSymbolFiles = {}
|
||||
def getSymbolFile(file, symbolsDir):
|
||||
|
Loading…
Reference in New Issue
Block a user