Breakpad Mac symbol dumper: Unify with Linux dumper; support DWARF CFI.

This patch rewrites the Mac symbol dumper to use the same set of classes
the Linux dumper does for reading debugging information from various
sources, consolidating them into a single table, and writing that out as a
Breakpad symbol file.

In the process, it also adds support for dumping DWARF call frame
information and .eh_frame exception-handling information as Breakpad 'STACK
CFI' records. This allows the Breakpad processor to generate stack traces
from code compiled with -fomit-frame-pointer.

The patch also replaces the DumpSymbols Objective C++ class with
google_breakpad::DumpSymbols, a plain C++ class. The code still uses some
Objective C++ to use the Foundation facilities for dealing with file names
in a file-system-independent fashion, and for examining the contents of
.dSYM bundles.

Since the code has been entirely rewritten, I have changed the author
lines.
A=jimb R=mark

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@614 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
ted.mielczarek 2010-06-25 16:56:42 +00:00
parent 9c1e16eaaa
commit 1adc07f0ff
5 changed files with 632 additions and 1228 deletions

View file

@ -8,6 +8,15 @@
/* Begin PBXBuildFile section */
B88FAE0B11665B5700407530 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; };
B88FAE1911665FE400407530 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1711665FE400407530 /* dwarf2diehandler.cc */; };
B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */; };
B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE201166603300407530 /* dwarf_line_to_module.cc */; };
B88FAE281166603300407530 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE221166603300407530 /* language.cc */; };
B88FAE291166603300407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
B88FAE2C1166606200407530 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; };
B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */; };
B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3911666C6F00407530 /* stabs_reader.cc */; settings = {COMPILER_FLAGS = "-DHAVE_MACH_O_NLIST_H"; }; };
B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3C11666C8900407530 /* stabs_to_module.cc */; };
B89E0E601166556C00DD08C9 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B89E0E5F1166556C00DD08C9 /* libcrypto.dylib */; };
B89E0E781166576C00DD08C9 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; };
B89E0E7A1166576C00DD08C9 /* macho_dump.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E701166573700DD08C9 /* macho_dump.cc */; };
@ -16,7 +25,6 @@
B89E0EA111665AC300DD08C9 /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E9F11665AC300DD08C9 /* gtest_main.cc */; };
B89E0EA211665AC300DD08C9 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0EA011665AC300DD08C9 /* gtest-all.cc */; };
B89E0EA411665AEA00DD08C9 /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0EA311665AEA00DD08C9 /* gmock-all.cc */; };
B8C5B5161166534700D34F4E /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ED420E8AD93000E953AD /* functioninfo.cc */; };
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */; };
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.cc */; };
B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 557800890BE1F3AB00EC23E0 /* macho_utilities.cc */; };
@ -43,6 +51,23 @@
9BE650460B52F6D800611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
B88FAE0911665B5700407530 /* test_assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_assembler.cc; path = ../../../common/test_assembler.cc; sourceTree = SOURCE_ROOT; };
B88FAE0A11665B5700407530 /* test_assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test_assembler.h; path = ../../../common/test_assembler.h; sourceTree = SOURCE_ROOT; };
B88FAE1711665FE400407530 /* dwarf2diehandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler.cc; path = ../../../common/dwarf/dwarf2diehandler.cc; sourceTree = SOURCE_ROOT; };
B88FAE1811665FE400407530 /* dwarf2diehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2diehandler.h; path = ../../../common/dwarf/dwarf2diehandler.h; sourceTree = SOURCE_ROOT; };
B88FAE1D1166603300407530 /* byte_cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byte_cursor.h; path = ../../../common/byte_cursor.h; sourceTree = SOURCE_ROOT; };
B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module.cc; path = ../../../common/dwarf_cu_to_module.cc; sourceTree = SOURCE_ROOT; };
B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cu_to_module.h; path = ../../../common/dwarf_cu_to_module.h; sourceTree = SOURCE_ROOT; };
B88FAE201166603300407530 /* dwarf_line_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module.cc; path = ../../../common/dwarf_line_to_module.cc; sourceTree = SOURCE_ROOT; };
B88FAE211166603300407530 /* dwarf_line_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_line_to_module.h; path = ../../../common/dwarf_line_to_module.h; sourceTree = SOURCE_ROOT; };
B88FAE221166603300407530 /* language.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = language.cc; path = ../../../common/language.cc; sourceTree = SOURCE_ROOT; };
B88FAE231166603300407530 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = language.h; path = ../../../common/language.h; sourceTree = SOURCE_ROOT; };
B88FAE241166603300407530 /* module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module.cc; path = ../../../common/module.cc; sourceTree = SOURCE_ROOT; };
B88FAE251166603300407530 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = module.h; path = ../../../common/module.h; sourceTree = SOURCE_ROOT; };
B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module.cc; path = ../../../common/dwarf_cfi_to_module.cc; sourceTree = SOURCE_ROOT; };
B88FAE341166673E00407530 /* dwarf_cfi_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cfi_to_module.h; path = ../../../common/dwarf_cfi_to_module.h; sourceTree = SOURCE_ROOT; };
B88FAE3911666C6F00407530 /* stabs_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader.cc; path = ../../../common/stabs_reader.cc; sourceTree = SOURCE_ROOT; };
B88FAE3A11666C6F00407530 /* stabs_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_reader.h; path = ../../../common/stabs_reader.h; sourceTree = SOURCE_ROOT; };
B88FAE3C11666C8900407530 /* stabs_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module.cc; path = ../../../common/stabs_to_module.cc; sourceTree = SOURCE_ROOT; };
B88FAE3D11666C8900407530 /* stabs_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_to_module.h; path = ../../../common/stabs_to_module.h; sourceTree = SOURCE_ROOT; };
B89E0E5F1166556C00DD08C9 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = /usr/lib/libcrypto.dylib; sourceTree = "<absolute>"; };
B89E0E6D1166571D00DD08C9 /* macho_reader_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader_unittest.cc; path = ../../../common/mac/macho_reader_unittest.cc; sourceTree = SOURCE_ROOT; };
B89E0E6E1166571D00DD08C9 /* macho_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader.cc; path = ../../../common/mac/macho_reader.cc; sourceTree = SOURCE_ROOT; };
@ -62,8 +87,6 @@
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -99,6 +122,8 @@
B89E0E9D11665A9500DD08C9 /* TESTING */,
F9F5344B0E7C8FFC0012363F /* DWARF */,
B89E0E6C1166569700DD08C9 /* MACHO */,
B88FAE3811666A1700407530 /* STABS */,
B88FAE1C11665FFD00407530 /* MODULE */,
B8E8CA0C1156C854009E61B2 /* byteswap.h */,
9BE650410B52F6D800611104 /* file_id.cc */,
9BE650420B52F6D800611104 /* file_id.h */,
@ -131,6 +156,35 @@
name = Products;
sourceTree = "<group>";
};
B88FAE1C11665FFD00407530 /* MODULE */ = {
isa = PBXGroup;
children = (
B88FAE1D1166603300407530 /* byte_cursor.h */,
B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */,
B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */,
B88FAE201166603300407530 /* dwarf_line_to_module.cc */,
B88FAE211166603300407530 /* dwarf_line_to_module.h */,
B88FAE221166603300407530 /* language.cc */,
B88FAE231166603300407530 /* language.h */,
B88FAE241166603300407530 /* module.cc */,
B88FAE251166603300407530 /* module.h */,
B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */,
B88FAE341166673E00407530 /* dwarf_cfi_to_module.h */,
B88FAE3C11666C8900407530 /* stabs_to_module.cc */,
B88FAE3D11666C8900407530 /* stabs_to_module.h */,
);
name = MODULE;
sourceTree = "<group>";
};
B88FAE3811666A1700407530 /* STABS */ = {
isa = PBXGroup;
children = (
B88FAE3911666C6F00407530 /* stabs_reader.cc */,
B88FAE3A11666C6F00407530 /* stabs_reader.h */,
);
name = STABS;
sourceTree = "<group>";
};
B89E0E6C1166569700DD08C9 /* MACHO */ = {
isa = PBXGroup;
children = (
@ -162,8 +216,6 @@
F9F5344B0E7C8FFC0012363F /* DWARF */ = {
isa = PBXGroup;
children = (
F9C7ED420E8AD93000E953AD /* functioninfo.cc */,
F9F5344D0E7C902C0012363F /* functioninfo.h */,
F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */,
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */,
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */,
@ -171,6 +223,8 @@
F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */,
F95B422C0E0E22D100DBDE83 /* bytereader.cc */,
F95B42310E0E22D100DBDE83 /* line_state_machine.h */,
B88FAE1711665FE400407530 /* dwarf2diehandler.cc */,
B88FAE1811665FE400407530 /* dwarf2diehandler.h */,
);
name = DWARF;
sourceTree = "<group>";
@ -231,9 +285,6 @@
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = NO;
};
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
@ -275,7 +326,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B8C5B5161166534700D34F4E /* functioninfo.cc in Sources */,
B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */,
@ -284,6 +335,14 @@
B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */,
B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */,
B8C5B51E1166534700D34F4E /* dump_syms_tool.mm in Sources */,
B88FAE1911665FE400407530 /* dwarf2diehandler.cc in Sources */,
B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */,
B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */,
B88FAE281166603300407530 /* language.cc in Sources */,
B88FAE291166603300407530 /* module.cc in Sources */,
B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */,
B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */,
B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -35,9 +35,14 @@
#include <mach-o/arch.h>
#include <unistd.h>
#include <vector>
#include "common/mac/dump_syms.h"
#include "common/mac/macho_utilities.h"
using google_breakpad::DumpSymbols;
using std::vector;
struct Options {
Options() : srcPath(), arch() { }
NSString *srcPath;
@ -46,24 +51,38 @@ struct Options {
//=============================================================================
static bool Start(const Options &options) {
DumpSymbols *dump = [[DumpSymbols alloc]
initWithContentsOfFile:options.srcPath];
if (!dump) {
fprintf(stderr, "%s is not a valid Mach-o file\n",
[options.srcPath fileSystemRepresentation]);
return false;
}
DumpSymbols dump_symbols;
if (![dump setArchitecture:[NSString
stringWithUTF8String:options.arch->name]]) {
fprintf(stderr, "Architecture: %s not available in %s\n",
options.arch->name,
[options.srcPath fileSystemRepresentation]);
if (!dump_symbols.Read(options.srcPath))
return false;
if (options.arch) {
if (!dump_symbols.SetArchitecture(options.arch->cputype,
options.arch->cpusubtype)) {
fprintf(stderr, "%s: no architecture '%s' is present in file.\n",
[options.srcPath fileSystemRepresentation], options.arch->name);
size_t available_size;
const struct fat_arch *available =
dump_symbols.AvailableArchitectures(&available_size);
if (available_size == 1)
fprintf(stderr, "the file's architecture is: ");
else
fprintf(stderr, "architectures present in the file are:\n");
for (size_t i = 0; i < available_size; i++) {
const struct fat_arch *arch = &available[i];
const NXArchInfo *arch_info =
NXGetArchInfoFromCpuType(arch->cputype, arch->cpusubtype);
if (arch_info)
fprintf(stderr, "%s (%s)\n", arch_info->name, arch_info->description);
else
fprintf(stderr, "unrecognized cpu type 0x%x, subtype 0x%x\n",
arch->cputype, arch->cpusubtype);
}
return false;
}
}
return [dump writeSymbolFile:@"-"];
return dump_symbols.WriteSymbolFile(stdout);
}
//=============================================================================
@ -71,7 +90,8 @@ static void Usage(int argc, const char *argv[]) {
fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
fprintf(stderr, "Usage: %s [-a ARCHITECTURE] <Mach-o file>\n",
argv[0]);
fprintf(stderr, "\t-a: Architecture type [default: native]\n");
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
fprintf(stderr, "\t-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n");
}
@ -81,8 +101,6 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind;
signed char ch;
options->arch = NXGetLocalArchInfo();
while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) {
switch (ch) {
case 'a': {