diff options
author | waylonis <waylonis@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2007-01-23 19:17:03 +0000 |
---|---|---|
committer | waylonis <waylonis@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2007-01-23 19:17:03 +0000 |
commit | d31c8b02925a1b20c09ee9ab771322353aea6267 (patch) | |
tree | 42696ec49303b9b114b05e8d8352b43e2f0b0a0a /src/common/mac | |
parent | Library to handle SymSrv integration (#111). r=bryner (diff) | |
download | breakpad-d31c8b02925a1b20c09ee9ab771322353aea6267.tar.xz |
Changes to support patch #108:
- Calculate unique file id for mach-o files
- Add file id support to dump_syms and symupload tools
- Fix return values of tools to indicate success or failure
- Change dump_syms class to be Objective-C++
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@109 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/mac')
-rw-r--r-- | src/common/mac/dump_syms.h | 6 | ||||
-rw-r--r-- | src/common/mac/dump_syms.mm (renamed from src/common/mac/dump_syms.m) | 227 | ||||
-rw-r--r-- | src/common/mac/macho_walker.cc | 5 |
3 files changed, 134 insertions, 104 deletions
diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h index 38c7d3ce..bfc96374 100644 --- a/src/common/mac/dump_syms.h +++ b/src/common/mac/dump_syms.h @@ -38,7 +38,6 @@ @protected NSString *sourcePath_; // Source of symbols (STRONG) NSString *architecture_; // Architecture to extract (STRONG) - NSString *uuidStr_; // Module UUID (STRONG) NSMutableDictionary *addresses_; // Addresses and symbols (STRONG) NSMutableDictionary *sources_; // Address and Source file paths (STRONG) NSMutableArray *cppAddresses_; // Addresses of C++ symbols (STRONG) @@ -56,11 +55,6 @@ - (BOOL)setArchitecture:(NSString *)architecture; - (NSString *)architecture; -// Specify a UUID to output with the symbol file. -// If none specified, a new one will be created -- (void)setUUID:(NSString *)uuidStr; -- (NSString *)uuid; - // Write the symbols to |symbolFilePath|. Return YES if successful. - (BOOL)writeSymbolFile:(NSString *)symbolFilePath; diff --git a/src/common/mac/dump_syms.m b/src/common/mac/dump_syms.mm index d133e120..86410cbe 100644 --- a/src/common/mac/dump_syms.m +++ b/src/common/mac/dump_syms.mm @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// dump_syms.m: Create a symbol file for use with minidumps +// dump_syms.mm: Create a symbol file for use with minidumps #include <unistd.h> #include <signal.h> @@ -43,6 +43,9 @@ #import <Foundation/Foundation.h> #import "dump_syms.h" +#import "common/mac/file_id.h" + +using google_airbag::FileID; static NSString *kAddressSymbolKey = @"symbol"; static NSString *kAddressConvertedSymbolKey = @"converted_symbol"; @@ -52,6 +55,7 @@ static NSString *kHeaderBaseAddressKey = @"baseAddr"; static NSString *kHeaderSizeKey = @"size"; static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header static NSString *kHeaderIs64BitKey = @"is64"; +static NSString *kHeaderCPUTypeKey = @"cpuType"; static NSString *kUnknownSymbol = @"???"; @interface DumpSymbols(PrivateMethods) @@ -70,6 +74,26 @@ static NSString *kUnknownSymbol = @"???"; - (NSMutableString *)generateSymbolFileString; @end +static BOOL StringHeadMatches(NSString *str, NSString *head) { + int headLen = [head length]; + int strLen = [str length]; + + if (headLen > strLen) + return NO; + + return [[str substringToIndex:headLen] isEqualToString:head]; +} + +static BOOL StringTailMatches(NSString *str, NSString *tail) { + int tailLen = [tail length]; + int strLen = [str length]; + + if (tailLen > strLen) + return NO; + + return [[str substringFromIndex:strLen - tailLen] isEqualToString:tail]; +} + @implementation DumpSymbols //============================================================================= - (NSString *)stringFromTask:(NSString *)action args:(NSArray *)args @@ -131,7 +155,7 @@ static NSString *kUnknownSymbol = @"???"; //============================================================================= - (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols { NSString *action = @"/usr/bin/c++filt"; - int count = [symbols count]; + unsigned int count = [symbols count]; // It's possible that we have too many symbols on the command line. // Unfortunately, c++filt doesn't take a file containing names, so we'll @@ -168,7 +192,7 @@ static NSString *kUnknownSymbol = @"???"; NSArray *addresses = [cppAddresses_ sortedArrayUsingSelector: @selector(compare:)]; - for (int i = 0; i < count; ++i) { + for (unsigned int i = 0; i < count; ++i) { NSMutableDictionary *dict = [addresses_ objectForKey: [addresses objectAtIndex:i]]; NSString *symbol = [dict objectForKey:kAddressSymbolKey]; @@ -183,7 +207,7 @@ static NSString *kUnknownSymbol = @"???"; NSArray *converted = [self convertCPlusPlusSymbols:symbols]; [symbols release]; - for (int i = 0; i < count; ++i) { + for (unsigned int i = 0; i < count; ++i) { NSMutableDictionary *dict = [addresses_ objectForKey: [addresses objectAtIndex:i]]; NSString *symbol = [converted objectAtIndex:i]; @@ -204,27 +228,26 @@ static NSString *kUnknownSymbol = @"???"; // If the function starts with "_Z" or "__Z" then add it to the list of // addresses to run through the c++filt BOOL isCPP = NO; - if ([name length] > 3) { - unichar buffer[3]; - [name getCharacters:buffer range:NSMakeRange(0, 3)]; - if (buffer[0] == '_') { - if (buffer[1] == '_' && buffer[2] == 'Z') { - // Remove the leading underscore - name = [name substringFromIndex:1]; - isCPP = YES; - } else if (buffer[1] == 'Z') { - isCPP = YES; - } - } + + if (StringHeadMatches(name, @"__Z")) { + // Remove the leading underscore + name = [name substringFromIndex:1]; + isCPP = YES; + } else if (StringHeadMatches(name, @"_Z")) { + isCPP = YES; } - if (isCPP) { - // Check if this is some debug symbol that ends in ".eh" I appears as - // though it's got to do with exception handling, but it's not the - // actual address of the function. So we'll ignore them - if ([[name substringFromIndex:[name length] - 3] isEqualToString:@".eh"]) - return; + // Filter out non-functions + if (StringTailMatches(name, @".eh")) + return; + + if (StringTailMatches(name, @"__func__")) + return; + if (StringTailMatches(name, @"GCC_except_table")) + return; + + if (isCPP) { if (!cppAddresses_) cppAddresses_ = [[NSMutableArray alloc] init]; [cppAddresses_ addObject:addressNum]; @@ -320,10 +343,11 @@ static NSString *kUnknownSymbol = @"???"; #define SwapShortIfNeeded(a) (swap ? NXSwapShort(a) : (a)) //============================================================================= - (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset { - struct mach_header *header = (struct mach_header *)(base + offset); + struct mach_header *header = (struct mach_header *)((uint32_t)base + offset); BOOL swap = (header->magic == MH_CIGAM); uint32_t count = SwapLongIfNeeded(header->ncmds); - struct load_command *cmd = (void *)header + sizeof(struct mach_header); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); uint32_t symbolTableCommand = SwapLongIfNeeded(LC_SYMTAB); BOOL result = NO; @@ -336,19 +360,18 @@ static NSString *kUnknownSymbol = @"???"; uint32_t ncmds = SwapLongIfNeeded(symtab->nsyms); uint32_t symoff = SwapLongIfNeeded(symtab->symoff); uint32_t stroff = SwapLongIfNeeded(symtab->stroff); - struct nlist *list = (struct nlist *)(base + symoff + offset); + struct nlist *list = (struct nlist *)((uint32_t)base + symoff + offset); char *strtab = ((char *)header + stroff); // Process each command, looking for debugging stuff for (uint32_t j = 0; j < ncmds; ++j, ++list) { // Fill in an nlist_64 structure and process with that - struct nlist_64 nlist64 = { - .n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx), - .n_type = list->n_type, - .n_sect = list->n_sect, - .n_desc = SwapIntIfNeeded(list->n_desc), - .n_value = (uint64_t)SwapLongIfNeeded(list->n_value) - }; + struct nlist_64 nlist64; + nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx); + nlist64.n_type = list->n_type; + nlist64.n_sect = list->n_sect; + nlist64.n_desc = SwapIntIfNeeded(list->n_desc); + nlist64.n_value = (uint64_t)SwapLongIfNeeded(list->n_value); if ([self processSymbolItem:&nlist64 stringTable:strtab]) result = YES; @@ -356,7 +379,7 @@ static NSString *kUnknownSymbol = @"???"; } uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); - cmd = (struct load_command *)((char *)cmd + cmdSize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); } return result; @@ -364,10 +387,12 @@ static NSString *kUnknownSymbol = @"???"; //============================================================================= - (BOOL)loadSymbolInfo64:(void *)base offset:(uint32_t)offset { - struct mach_header_64 *header = (struct mach_header_64 *)(base + offset); + struct mach_header_64 *header = (struct mach_header_64 *) + ((uint32_t)base + offset); BOOL swap = (header->magic == MH_CIGAM_64); uint32_t count = SwapLongIfNeeded(header->ncmds); - struct load_command *cmd = (void *)header + sizeof(struct mach_header); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); uint32_t symbolTableCommand = SwapLongIfNeeded(LC_SYMTAB); BOOL result = NO; @@ -377,7 +402,7 @@ static NSString *kUnknownSymbol = @"???"; uint32_t ncmds = SwapLongIfNeeded(symtab->nsyms); uint32_t symoff = SwapLongIfNeeded(symtab->symoff); uint32_t stroff = SwapLongIfNeeded(symtab->stroff); - struct nlist_64 *list = (struct nlist_64 *)(base + symoff); + struct nlist_64 *list = (struct nlist_64 *)((uint32_t)base + symoff); char *strtab = ((char *)header + stroff); // Process each command, looking for debugging stuff @@ -386,13 +411,12 @@ static NSString *kUnknownSymbol = @"???"; continue; // Fill in an nlist_64 structure and process with that - struct nlist_64 nlist64 = { - .n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx), - .n_type = list->n_type, - .n_sect = list->n_sect, - .n_desc = SwapIntIfNeeded(list->n_desc), - .n_value = SwapLongLongIfNeeded(list->n_value) - }; + struct nlist_64 nlist64; + nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx); + nlist64.n_type = list->n_type; + nlist64.n_sect = list->n_sect; + nlist64.n_desc = SwapIntIfNeeded(list->n_desc); + nlist64.n_value = SwapLongLongIfNeeded(list->n_value); if ([self processSymbolItem:&nlist64 stringTable:strtab]) result = YES; @@ -400,7 +424,7 @@ static NSString *kUnknownSymbol = @"???"; } uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); - cmd = (struct load_command *)((char *)cmd + cmdSize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); } return result; @@ -411,7 +435,7 @@ static NSString *kUnknownSymbol = @"???"; NSMutableData *data = [[NSMutableData alloc] initWithContentsOfMappedFile:sourcePath_]; NSDictionary *headerInfo = [headers_ objectForKey:architecture_]; - char *base = [data mutableBytes]; + void *base = [data mutableBytes]; uint32_t offset = [[headerInfo objectForKey:kHeaderOffsetKey] unsignedLongValue]; BOOL is64 = [[headerInfo objectForKey:kHeaderIs64BitKey] boolValue]; @@ -424,10 +448,11 @@ static NSString *kUnknownSymbol = @"???"; //============================================================================= - (BOOL)loadHeader:(void *)base offset:(uint32_t)offset { - struct mach_header *header = (struct mach_header *)(base + offset); + struct mach_header *header = (struct mach_header *)((uint32_t)base + offset); BOOL swap = (header->magic == MH_CIGAM); uint32_t count = SwapLongIfNeeded(header->ncmds); - struct load_command *cmd = (void *)header + sizeof(struct mach_header); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header)); for (uint32_t i = 0; cmd && (i < count); i++) { uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT); @@ -445,6 +470,7 @@ static NSString *kUnknownSymbol = @"???"; [NSNumber numberWithUnsignedLongLong:(uint64_t)size], kHeaderSizeKey, [NSNumber numberWithUnsignedLong:offset], kHeaderOffsetKey, [NSNumber numberWithBool:NO], kHeaderIs64BitKey, + [NSNumber numberWithUnsignedLong:cpu], kHeaderCPUTypeKey, nil] forKey:cpuStr]; return YES; @@ -452,7 +478,7 @@ static NSString *kUnknownSymbol = @"???"; } uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); - cmd = (struct load_command *)((char *)cmd + cmdSize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); } return NO; @@ -460,10 +486,12 @@ static NSString *kUnknownSymbol = @"???"; //============================================================================= - (BOOL)loadHeader64:(void *)base offset:(uint32_t)offset { - struct mach_header_64 *header = (struct mach_header_64 *)(base + offset); + struct mach_header_64 *header = + (struct mach_header_64 *)((uint32_t)base + offset); BOOL swap = (header->magic == MH_CIGAM_64); uint32_t count = SwapLongIfNeeded(header->ncmds); - struct load_command *cmd = (void *)header + sizeof(struct mach_header_64); + struct load_command *cmd = + (struct load_command *)((uint32_t)header + sizeof(struct mach_header_64)); for (uint32_t i = 0; cmd && (i < count); i++) { uint32_t segmentCommand = SwapLongIfNeeded(LC_SEGMENT_64); @@ -487,7 +515,7 @@ static NSString *kUnknownSymbol = @"???"; } uint32_t cmdSize = SwapLongIfNeeded(cmd->cmdsize); - cmd = (struct load_command *)((char *)cmd + cmdSize); + cmd = (struct load_command *)((uint32_t)cmd + cmdSize); } return NO; @@ -498,7 +526,7 @@ static NSString *kUnknownSymbol = @"???"; uint64_t result = 0; NSMutableData *data = [[NSMutableData alloc] initWithContentsOfMappedFile:sourcePath_]; - char *bytes = [data mutableBytes]; + void *bytes = [data mutableBytes]; struct fat_header *fat = (struct fat_header *)bytes; if (!fat) { @@ -523,7 +551,7 @@ static NSString *kUnknownSymbol = @"???"; if (isFat) { struct fat_arch *archs = - (struct fat_arch *)((void *)fat + sizeof(struct fat_header)); + (struct fat_arch *)((uint32_t)fat + sizeof(struct fat_header)); uint32_t count = SwapLongIfNeeded(fat->nfat_arch); for (uint32_t i = 0; i < count; ++i) { @@ -583,17 +611,36 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { NSArray *sortedAddresses = [[addresses_ allKeys] sortedArrayUsingSelector:@selector(compare:)]; - // Module - if (!WriteFormat(fd, "MODULE mac %s %s 1 %s\n", [architecture_ UTF8String], - [uuidStr_ UTF8String], - [[sourcePath_ lastPathComponent] UTF8String])) + // UUID + FileID file_id([sourcePath_ fileSystemRepresentation]); + unsigned char identifier[16]; + char identifierStr[40]; + const char *moduleName = [[sourcePath_ lastPathComponent] UTF8String]; + int cpu_type = [[archDict objectForKey:kHeaderCPUTypeKey] unsignedLongValue]; + if (file_id.MachoIdentifier(cpu_type, identifier)) { + FileID::ConvertIdentifierToString(identifier, identifierStr, + sizeof(identifierStr)); + } + else { + strlcpy(identifierStr, moduleName, sizeof(identifierStr)); + } + + // Remove the dashes from the string + NSMutableString *compactedStr = + [NSMutableString stringWithCString:identifierStr encoding:NSASCIIStringEncoding]; + [compactedStr replaceOccurrencesOfString:@"-" withString:@"" options:0 + range:NSMakeRange(0, [compactedStr length])]; + + if (!WriteFormat(fd, "MODULE mac %s %s0 %s\n", [architecture_ UTF8String], + [compactedStr UTF8String], moduleName)) { return NO; + } // Sources ordered by address - NSArray *sources = [[sources_ allKeys] + NSArray *sources = [[sources_ allKeys] sortedArrayUsingSelector:@selector(compare:)]; - int sourceCount = [sources count]; - for (int i = 0; i < sourceCount; ++i) { + unsigned int sourceCount = [sources count]; + for (unsigned int i = 0; i < sourceCount; ++i) { NSString *file = [sources_ objectForKey:[sources objectAtIndex:i]]; if (!WriteFormat(fd, "FILE %d %s\n", i + 1, [file UTF8String])) return NO; @@ -605,9 +652,9 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { uint64_t nextSourceFileAddress = 0; NSNumber *nextAddress; uint64_t nextAddressVal; - int addressCount = [sortedAddresses count]; + unsigned int addressCount = [sortedAddresses count]; - for (int i = 0; i < addressCount; ++i) { + for (unsigned int i = 0; i < addressCount; ++i) { NSNumber *address = [sortedAddresses objectAtIndex:i]; uint64_t addressVal = [address unsignedLongLongValue] - baseAddress; @@ -625,6 +672,22 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { NSNumber *line = [dict objectForKey:kAddressSourceLineKey]; NSString *symbol = [dict objectForKey:kAddressConvertedSymbolKey]; + if (!symbol) + symbol = [dict objectForKey:kAddressSymbolKey]; + + // Skip some symbols + if (StringHeadMatches(symbol, @"__gnu")) + continue; + + if (StringHeadMatches(symbol, @"typeinfo ")) + continue; + + if (StringHeadMatches(symbol, @"EH_frame")) + continue; + + if (StringHeadMatches(symbol, @"GCC_except_table")) + continue; + // Find the source file (if any) that contains this address while (sourceCount && (addressVal >= nextSourceFileAddress)) { fileIdx = nextFileIdx; @@ -635,33 +698,30 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { nextSourceFileAddress = [addr unsignedLongLongValue] - baseAddress; } else { nextSourceFileAddress = baseAddress + moduleSize; + break; } } - if (!symbol) - symbol = [dict objectForKey:kAddressSymbolKey]; - if (line) { if (symbol) { NSNumber *functionLength = [dict objectForKey:kFunctionSizeKey]; uint64_t functionLengthVal = [functionLength unsignedLongLongValue]; // Function - if (!WriteFormat(fd, "FUNC %llx %llx 0 %s%c", addressVal, - functionLengthVal, [symbol UTF8String], - terminatingChar)) + if (!WriteFormat(fd, "FUNC %llx %llx 0 %s\n", addressVal, + functionLengthVal, [symbol UTF8String])) return NO; } // Source line uint64_t length = nextAddressVal - addressVal; - if (!WriteFormat(fd, "%llx %llx %d %d%c", addressVal, length, - [line unsignedIntValue], fileIdx, terminatingChar)) + if (!WriteFormat(fd, "%llx %llx %d %d\n", addressVal, length, + [line unsignedIntValue], fileIdx)) return NO; } else { // PUBLIC <address> <stack-size> <name> - if (!WriteFormat(fd, "PUBLIC %llx 0 %s%c", addressVal, - [symbol UTF8String], terminatingChar)) + if (!WriteFormat(fd, "PUBLIC %llx 0 %s\n", addressVal, + [symbol UTF8String])) return NO; } } @@ -671,10 +731,9 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { //============================================================================= - (id)initWithContentsOfFile:(NSString *)path { - if (self = [super init]) { + if ((self = [super init])) { if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { - NSLog(@"Missing source file: %@", path); [self autorelease]; return nil; } @@ -682,7 +741,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { sourcePath_ = [path copy]; if (![self loadModuleInfo]) { - NSLog(@"Not a valid Mach-o file: %@", path); [self autorelease]; return nil; } @@ -707,8 +765,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { // Specify the default architecture [self setArchitecture:[[headers_ allKeys] objectAtIndex:0]]; } - - [self setUUID:nil]; } return self; @@ -723,7 +779,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { - (void)dealloc { [sourcePath_ release]; [architecture_ release]; - [uuidStr_ release]; [addresses_ release]; [sources_ release]; [headers_ release]; @@ -770,22 +825,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) { } //============================================================================= -- (void)setUUID:(NSString *)uuidStr { - if (!uuidStr) { - CFUUIDRef uuid = CFUUIDCreate(NULL); - uuidStr = [(NSString *)CFUUIDCreateString(NULL, uuid) autorelease]; - } - - [uuidStr_ autorelease]; - uuidStr_ = [uuidStr copy]; -} - -//============================================================================= -- (NSString *)uuid { - return uuidStr_; -} - -//============================================================================= - (BOOL)writeSymbolFile:(NSString *)destinationPath { const char *dest = [destinationPath fileSystemRepresentation]; int fd; diff --git a/src/common/mac/macho_walker.cc b/src/common/mac/macho_walker.cc index 96dca406..5e9de5f4 100644 --- a/src/common/mac/macho_walker.cc +++ b/src/common/mac/macho_walker.cc @@ -103,7 +103,7 @@ bool MachoWalker::FindHeader(int cpu_type, off_t &offset) { offset = sizeof(magic); // Figure out what type of file we've got - bool is_fat; + bool is_fat = false; if (magic == FAT_MAGIC || magic == FAT_CIGAM) { is_fat = true; } @@ -119,9 +119,6 @@ bool MachoWalker::FindHeader(int cpu_type, off_t &offset) { if (!ReadBytes(&header_cpu_type, sizeof(header_cpu_type), offset)) return false; - if (NXHostByteOrder() != NX_BigEndian) - header_cpu_type = NXSwapLong(header_cpu_type); - if (valid_cpu_type != header_cpu_type) return false; |