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

@ -1,4 +1,6 @@
// Copyright (c) 2006, Google Inc. // -*- mode: c++ -*-
// Copyright (c) 2010, Google Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -27,53 +29,133 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// dump_syms.h: Interface for DumpSymbols. This class will take a mach-o file // Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
// and extract the symbol information and write it to a file using the
// breakpad symbol file format.
#import <Foundation/Foundation.h> // dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for
// reading debugging information from Mach-O files and writing it out as a
// Breakpad symbol file.
#include <Foundation/Foundation.h>
#include <mach-o/loader.h> #include <mach-o/loader.h>
#include "common/dwarf/dwarf2reader.h" #include <stdio.h>
#include <stdlib.h>
// This will map from an architecture string to a SectionMap, which #include <string>
// will contain the offsets for all the sections in the dictionary #include <vector>
typedef map<string, dwarf2reader::SectionMap *> ArchSectionMap;
@interface DumpSymbols : NSObject { #include "common/byte_cursor.h"
@protected #include "common/mac/macho_reader.h"
NSString *sourcePath_; // Source of symbols (STRONG) #include "common/module.h"
NSString *architecture_; // Architecture to extract (STRONG)
NSMutableDictionary *addresses_; // Addresses and symbols (STRONG)
NSMutableSet *functionAddresses_; // Function addresses (STRONG)
NSMutableDictionary *sources_; // Address and Source file paths (STRONG)
NSMutableDictionary *headers_; // Mach-o header information (STRONG)
NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG)
uint32_t lastStartAddress_;
ArchSectionMap *sectionsForArch_;
}
- (id)initWithContentsOfFile:(NSString *)machoFile; namespace google_breakpad {
- (NSArray *)availableArchitectures; class DumpSymbols {
public:
DumpSymbols()
: input_pathname_(),
object_filename_(),
contents_(),
selected_object_file_(),
selected_object_name_() { }
~DumpSymbols() {
[input_pathname_ release];
[object_filename_ release];
[contents_ release];
}
// One of ppc, x86, i386, ppc64, x86_64 // Prepare to read debugging information from |filename|. |filename| may be
// If the architecture is not available, it will return NO // the name of a universal binary, a Mach-O file, or a dSYM bundle
// If not set, the native architecture will be used // containing either of the above. On success, return true; if there is a
- (BOOL)setArchitecture:(NSString *)architecture; // problem reading |filename|, report it and return false.
- (NSString *)architecture; //
// (This class uses NSString for filenames and related values,
// because the Mac Foundation framework seems to support
// filename-related operations more fully on NSString values.)
bool Read(NSString *filename);
// Write the symbols to |symbolFilePath|. Return YES if successful. // If this dumper's file includes an object file for |cpu_type| and
- (BOOL)writeSymbolFile:(NSString *)symbolFilePath; // |cpu_subtype|, then select that object file for dumping, and return
// true. Otherwise, return false, and leave this dumper's selected
// architecture unchanged.
//
// By default, if this dumper's file contains only one object file, then
// the dumper will dump those symbols; and if it contains more than one
// object file, then the dumper will dump the object file whose
// architecture matches that of this dumper program.
bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
@end // Return a pointer to an array of 'struct fat_arch' structures,
// describing the object files contained in this dumper's file. Set
// *|count| to the number of elements in the array. The returned array is
// owned by this DumpSymbols instance.
//
// If there are no available architectures, this function
// may return NULL.
const struct fat_arch *AvailableArchitectures(size_t *count) {
*count = object_files_.size();
if (object_files_.size() > 0)
return &object_files_[0];
return NULL;
}
@interface MachSection : NSObject { // Read the selected object file's debugging information, and write it
@protected // out to |stream|. Return true on success; if an error occurs, report it
struct section *sect_; // and return false.
uint32_t sectionNumber_; bool WriteSymbolFile(FILE *stream);
}
- (id)initWithMachSection:(struct section *)sect andNumber:(uint32_t)sectionNumber;
- (struct section*)sectionPointer;
- (uint32_t)sectionNumber;
@end private:
// Used internally.
class DumperLineToModule;
class LoadCommandDumper;
// Return an identifier string for the file this DumpSymbols is dumping.
std::string Identifier();
// Read debugging information from |dwarf_sections|, which was taken from
// |macho_reader|, and add it to |module|. On success, return true;
// on failure, report the problem and return false.
bool ReadDwarf(google_breakpad::Module *module,
const mach_o::Reader &macho_reader,
const mach_o::SectionMap &dwarf_sections) const;
// Read DWARF CFI or .eh_frame data from |section|, belonging to
// |macho_reader|, and record it in |module|. If |eh_frame| is true,
// then the data is .eh_frame-format data; otherwise, it is standard DWARF
// .debug_frame data. On success, return true; on failure, report
// the problem and return false.
bool ReadCFI(google_breakpad::Module *module,
const mach_o::Reader &macho_reader,
const mach_o::Section &section,
bool eh_frame) const;
// The name of the file or bundle whose symbols this will dump.
// This is the path given to Read, for use in error messages.
NSString *input_pathname_;
// The name of the file this DumpSymbols will actually read debugging
// information from. Normally, this is the same as input_pathname_, but if
// filename refers to a dSYM bundle, then this is the resource file
// within that bundle.
NSString *object_filename_;
// The complete contents of object_filename_, mapped into memory.
NSData *contents_;
// A vector of fat_arch structures describing the object files
// object_filename_ contains. If object_filename_ refers to a fat binary,
// this may have more than one element; if it refers to a Mach-O file, this
// has exactly one element.
vector<struct fat_arch> object_files_;
// The object file in object_files_ selected to dump, or NULL if
// SetArchitecture hasn't been called yet.
const struct fat_arch *selected_object_file_;
// A string that identifies the selected object file, for use in error
// messages. This is usually object_filename_, but if that refers to a
// fat binary, it includes an indication of the particular architecture
// within that binary.
string selected_object_name_;
};
} // namespace google_breakpad

File diff suppressed because it is too large Load Diff

View File

@ -62,22 +62,11 @@ MachoWalker::~MachoWalker() {
} }
int MachoWalker::ValidateCPUType(int cpu_type) { int MachoWalker::ValidateCPUType(int cpu_type) {
// If the user didn't specify, try to use the local architecture. If that // If the user didn't specify, use the local architecture.
// fails, use the base type for the executable.
if (cpu_type == 0) { if (cpu_type == 0) {
const NXArchInfo *arch = NXGetLocalArchInfo(); const NXArchInfo *arch = NXGetLocalArchInfo();
if (arch) assert(arch);
cpu_type = arch->cputype; cpu_type = arch->cputype;
else
#if __ppc__
cpu_type = CPU_TYPE_POWERPC;
#elif __i386__
cpu_type = CPU_TYPE_X86;
#elif __x86_64__
cpu_type = CPU_TYPE_X86_64;
#else
#error Unknown architecture -- are you on a PDP-11?
#endif
} }
return cpu_type; return cpu_type;

View File

@ -8,6 +8,15 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
B88FAE0B11665B5700407530 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; }; 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 */; }; B89E0E601166556C00DD08C9 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B89E0E5F1166556C00DD08C9 /* libcrypto.dylib */; };
B89E0E781166576C00DD08C9 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */; };
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.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 */; }; 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; }; 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; }; 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; }; 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>"; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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 */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -99,6 +122,8 @@
B89E0E9D11665A9500DD08C9 /* TESTING */, B89E0E9D11665A9500DD08C9 /* TESTING */,
F9F5344B0E7C8FFC0012363F /* DWARF */, F9F5344B0E7C8FFC0012363F /* DWARF */,
B89E0E6C1166569700DD08C9 /* MACHO */, B89E0E6C1166569700DD08C9 /* MACHO */,
B88FAE3811666A1700407530 /* STABS */,
B88FAE1C11665FFD00407530 /* MODULE */,
B8E8CA0C1156C854009E61B2 /* byteswap.h */, B8E8CA0C1156C854009E61B2 /* byteswap.h */,
9BE650410B52F6D800611104 /* file_id.cc */, 9BE650410B52F6D800611104 /* file_id.cc */,
9BE650420B52F6D800611104 /* file_id.h */, 9BE650420B52F6D800611104 /* file_id.h */,
@ -131,6 +156,35 @@
name = Products; name = Products;
sourceTree = "<group>"; 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 */ = { B89E0E6C1166569700DD08C9 /* MACHO */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -162,8 +216,6 @@
F9F5344B0E7C8FFC0012363F /* DWARF */ = { F9F5344B0E7C8FFC0012363F /* DWARF */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F9C7ED420E8AD93000E953AD /* functioninfo.cc */,
F9F5344D0E7C902C0012363F /* functioninfo.h */,
F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */, F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */,
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */, F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */,
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */, F95B42300E0E22D100DBDE83 /* dwarf2reader.h */,
@ -171,6 +223,8 @@
F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */, F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */,
F95B422C0E0E22D100DBDE83 /* bytereader.cc */, F95B422C0E0E22D100DBDE83 /* bytereader.cc */,
F95B42310E0E22D100DBDE83 /* line_state_machine.h */, F95B42310E0E22D100DBDE83 /* line_state_machine.h */,
B88FAE1711665FE400407530 /* dwarf2diehandler.cc */,
B88FAE1811665FE400407530 /* dwarf2diehandler.h */,
); );
name = DWARF; name = DWARF;
sourceTree = "<group>"; sourceTree = "<group>";
@ -231,9 +285,6 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = { 08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = NO;
};
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */; buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
compatibilityVersion = "Xcode 2.4"; compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
@ -275,7 +326,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
B8C5B5161166534700D34F4E /* functioninfo.cc in Sources */, B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */, B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */, B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */, B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */,
@ -284,6 +335,14 @@
B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */, B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */,
B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */, B8C5B51D1166534700D34F4E /* dump_syms.mm in Sources */,
B8C5B51E1166534700D34F4E /* dump_syms_tool.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; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -35,9 +35,14 @@
#include <mach-o/arch.h> #include <mach-o/arch.h>
#include <unistd.h> #include <unistd.h>
#include <vector>
#include "common/mac/dump_syms.h" #include "common/mac/dump_syms.h"
#include "common/mac/macho_utilities.h" #include "common/mac/macho_utilities.h"
using google_breakpad::DumpSymbols;
using std::vector;
struct Options { struct Options {
Options() : srcPath(), arch() { } Options() : srcPath(), arch() { }
NSString *srcPath; NSString *srcPath;
@ -46,24 +51,38 @@ struct Options {
//============================================================================= //=============================================================================
static bool Start(const Options &options) { static bool Start(const Options &options) {
DumpSymbols *dump = [[DumpSymbols alloc] DumpSymbols dump_symbols;
initWithContentsOfFile:options.srcPath];
if (!dump) { if (!dump_symbols.Read(options.srcPath))
fprintf(stderr, "%s is not a valid Mach-o file\n",
[options.srcPath fileSystemRepresentation]);
return false; 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;
}
} }
if (![dump setArchitecture:[NSString return dump_symbols.WriteSymbolFile(stdout);
stringWithUTF8String:options.arch->name]]) {
fprintf(stderr, "Architecture: %s not available in %s\n",
options.arch->name,
[options.srcPath fileSystemRepresentation]);
return false;
}
return [dump writeSymbolFile:@"-"];
} }
//============================================================================= //=============================================================================
@ -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, "Output a Breakpad symbol file from a Mach-o file.\n");
fprintf(stderr, "Usage: %s [-a ARCHITECTURE] <Mach-o file>\n", fprintf(stderr, "Usage: %s [-a ARCHITECTURE] <Mach-o file>\n",
argv[0]); 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-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n"); fprintf(stderr, "\t-?: Usage\n");
} }
@ -81,8 +101,6 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind; extern int optind;
signed char ch; signed char ch;
options->arch = NXGetLocalArchInfo();
while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) { while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) {
switch (ch) { switch (ch) {
case 'a': { case 'a': {