mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-28 01:14:20 +01:00
Issue 146 - reviewer Waylonis
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@137 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
1de8bed899
commit
aa870d0c1b
@ -39,11 +39,12 @@
|
|||||||
NSString *sourcePath_; // Source of symbols (STRONG)
|
NSString *sourcePath_; // Source of symbols (STRONG)
|
||||||
NSString *architecture_; // Architecture to extract (STRONG)
|
NSString *architecture_; // Architecture to extract (STRONG)
|
||||||
NSMutableDictionary *addresses_; // Addresses and symbols (STRONG)
|
NSMutableDictionary *addresses_; // Addresses and symbols (STRONG)
|
||||||
|
NSMutableSet *functionAddresses_; // Function addresses (STRONG)
|
||||||
NSMutableDictionary *sources_; // Address and Source file paths (STRONG)
|
NSMutableDictionary *sources_; // Address and Source file paths (STRONG)
|
||||||
NSMutableArray *cppAddresses_; // Addresses of C++ symbols (STRONG)
|
NSMutableArray *cppAddresses_; // Addresses of C++ symbols (STRONG)
|
||||||
NSMutableDictionary *headers_; // Mach-o header information (STRONG)
|
NSMutableDictionary *headers_; // Mach-o header information (STRONG)
|
||||||
NSMutableDictionary *lastFunctionStartDict_; // Keyed by section# (STRONG)
|
|
||||||
NSMutableDictionary *sectionNumbers_; // Keyed by seg/sect name (STRONG)
|
NSMutableDictionary *sectionNumbers_; // Keyed by seg/sect name (STRONG)
|
||||||
|
uint32_t lastStartAddress_;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithContentsOfFile:(NSString *)machoFile;
|
- (id)initWithContentsOfFile:(NSString *)machoFile;
|
||||||
|
@ -269,17 +269,16 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
[dict release];
|
[dict release];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name && ![dict objectForKey:kAddressSymbolKey])
|
if (name && ![dict objectForKey:kAddressSymbolKey]) {
|
||||||
[dict setObject:name forKey:kAddressSymbolKey];
|
[dict setObject:name forKey:kAddressSymbolKey];
|
||||||
|
|
||||||
|
// only functions, not line number addresses
|
||||||
|
[functionAddresses_ addObject:addressNum];
|
||||||
|
}
|
||||||
|
|
||||||
if (line && ![dict objectForKey:kAddressSourceLineKey])
|
if (line && ![dict objectForKey:kAddressSourceLineKey])
|
||||||
[dict setObject:[NSNumber numberWithUnsignedInt:line]
|
[dict setObject:[NSNumber numberWithUnsignedInt:line]
|
||||||
forKey:kAddressSourceLineKey];
|
forKey:kAddressSourceLineKey];
|
||||||
|
|
||||||
// Save the function name so that we can add the end of function address
|
|
||||||
if ([name length]) {
|
|
||||||
[lastFunctionStartDict_ setObject:addressNum forKey:[NSNumber numberWithUnsignedInt:section] ];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@ -287,10 +286,32 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
uint32_t n_strx = list->n_un.n_strx;
|
uint32_t n_strx = list->n_un.n_strx;
|
||||||
BOOL result = NO;
|
BOOL result = NO;
|
||||||
|
|
||||||
// We don't care about non-section specific information
|
// We don't care about non-section specific information except function length
|
||||||
if (list->n_sect == 0 )
|
if (list->n_sect == 0 && list->n_type != N_FUN )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
|
if (list->n_type == N_FUN) {
|
||||||
|
if (list->n_sect != 0) {
|
||||||
|
// we get the function address from the first N_FUN
|
||||||
|
lastStartAddress_ = list->n_value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// an N_FUN from section 0 may follow the initial N_FUN
|
||||||
|
// giving us function length information
|
||||||
|
NSMutableDictionary *dict = [addresses_ objectForKey:
|
||||||
|
[NSNumber numberWithUnsignedLong:lastStartAddress_] ];
|
||||||
|
|
||||||
|
assert(dict);
|
||||||
|
|
||||||
|
// only set the function size the first time
|
||||||
|
// (sometimes multiple section 0 N_FUN entries appear!)
|
||||||
|
if (![dict objectForKey:kFunctionSizeKey]) {
|
||||||
|
[dict setObject:[NSNumber numberWithUnsignedLongLong:list->n_value]
|
||||||
|
forKey:kFunctionSizeKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int line = list->n_desc;
|
int line = list->n_desc;
|
||||||
|
|
||||||
// We only care about line number information in __TEXT __text
|
// We only care about line number information in __TEXT __text
|
||||||
@ -298,7 +319,7 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
if(list->n_sect != mainSection) {
|
if(list->n_sect != mainSection) {
|
||||||
line = 0;
|
line = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract debugging information:
|
// Extract debugging information:
|
||||||
// Doc: http://developer.apple.com/documentation/DeveloperTools/gdb/stabs/stabs_toc.html
|
// Doc: http://developer.apple.com/documentation/DeveloperTools/gdb/stabs/stabs_toc.html
|
||||||
// Header: /usr/include/mach-o/stab.h:
|
// Header: /usr/include/mach-o/stab.h:
|
||||||
@ -336,24 +357,9 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
} else if (((list->n_type & N_TYPE) == N_SECT) && !(list->n_type & N_STAB)) {
|
} else if (((list->n_type & N_TYPE) == N_SECT) && !(list->n_type & N_STAB)) {
|
||||||
// Regular symbols or ones that are external
|
// Regular symbols or ones that are external
|
||||||
NSString *fn = [NSString stringWithUTF8String:&table[n_strx]];
|
NSString *fn = [NSString stringWithUTF8String:&table[n_strx]];
|
||||||
|
|
||||||
[self addFunction:fn line:0 address:list->n_value section:list->n_sect ];
|
[self addFunction:fn line:0 address:list->n_value section:list->n_sect ];
|
||||||
result = YES;
|
result = YES;
|
||||||
} else if (list->n_type == N_ENSYM && list->n_sect == mainSection ) {
|
|
||||||
NSNumber *lastFunctionStart = [lastFunctionStartDict_
|
|
||||||
objectForKey:[NSNumber numberWithUnsignedLongLong:list->n_sect] ];
|
|
||||||
|
|
||||||
if (lastFunctionStart) {
|
|
||||||
unsigned long long start = [lastFunctionStart unsignedLongLongValue];
|
|
||||||
unsigned long long size = list->n_value - start;
|
|
||||||
NSMutableDictionary *dict = [addresses_ objectForKey:lastFunctionStart];
|
|
||||||
assert(dict);
|
|
||||||
assert(list->n_value > start);
|
|
||||||
|
|
||||||
[dict setObject:[NSNumber numberWithUnsignedLongLong:size]
|
|
||||||
forKey:kFunctionSizeKey];
|
|
||||||
|
|
||||||
[lastFunctionStartDict_ removeObjectForKey:[NSNumber numberWithUnsignedLongLong:list->n_sect] ];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -392,7 +398,7 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx);
|
nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx);
|
||||||
nlist64.n_type = list->n_type;
|
nlist64.n_type = list->n_type;
|
||||||
nlist64.n_sect = list->n_sect;
|
nlist64.n_sect = list->n_sect;
|
||||||
nlist64.n_desc = SwapIntIfNeeded(list->n_desc);
|
nlist64.n_desc = SwapShortIfNeeded(list->n_desc);
|
||||||
nlist64.n_value = (uint64_t)SwapLongIfNeeded(list->n_value);
|
nlist64.n_value = (uint64_t)SwapLongIfNeeded(list->n_value);
|
||||||
|
|
||||||
if ([self processSymbolItem:&nlist64 stringTable:strtab])
|
if ([self processSymbolItem:&nlist64 stringTable:strtab])
|
||||||
@ -437,7 +443,7 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
|
|||||||
nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx);
|
nlist64.n_un.n_strx = SwapLongIfNeeded(list->n_un.n_strx);
|
||||||
nlist64.n_type = list->n_type;
|
nlist64.n_type = list->n_type;
|
||||||
nlist64.n_sect = list->n_sect;
|
nlist64.n_sect = list->n_sect;
|
||||||
nlist64.n_desc = SwapIntIfNeeded(list->n_desc);
|
nlist64.n_desc = SwapShortIfNeeded(list->n_desc);
|
||||||
nlist64.n_value = SwapLongLongIfNeeded(list->n_value);
|
nlist64.n_value = SwapLongLongIfNeeded(list->n_value);
|
||||||
|
|
||||||
if ([self processSymbolItem:&nlist64 stringTable:strtab])
|
if ([self processSymbolItem:&nlist64 stringTable:strtab])
|
||||||
@ -668,15 +674,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
uint64_t moduleSize =
|
uint64_t moduleSize =
|
||||||
moduleSizeNum ? [moduleSizeNum unsignedLongLongValue] : 0;
|
moduleSizeNum ? [moduleSizeNum unsignedLongLongValue] : 0;
|
||||||
|
|
||||||
[lastFunctionStartDict_ removeAllObjects];
|
|
||||||
|
|
||||||
// Gather the information
|
|
||||||
[self loadSymbolInfoForArchitecture];
|
|
||||||
[self convertSymbols];
|
|
||||||
|
|
||||||
NSArray *sortedAddresses = [[addresses_ allKeys]
|
|
||||||
sortedArrayUsingSelector:@selector(compare:)];
|
|
||||||
|
|
||||||
// UUID
|
// UUID
|
||||||
FileID file_id([sourcePath_ fileSystemRepresentation]);
|
FileID file_id([sourcePath_ fileSystemRepresentation]);
|
||||||
unsigned char identifier[16];
|
unsigned char identifier[16];
|
||||||
@ -688,9 +685,27 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
sizeof(identifierStr));
|
sizeof(identifierStr));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strlcpy(identifierStr, moduleName, sizeof(identifierStr));
|
fprintf(stderr, "Unable to calculate UUID of mach-o binary!\n");
|
||||||
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keep track exclusively of function addresses
|
||||||
|
// for sanity checking function lengths
|
||||||
|
functionAddresses_ = [[NSMutableSet alloc] init];
|
||||||
|
|
||||||
|
// Gather the information
|
||||||
|
[self loadSymbolInfoForArchitecture];
|
||||||
|
[self convertSymbols];
|
||||||
|
|
||||||
|
NSArray *sortedAddresses = [[addresses_ allKeys]
|
||||||
|
sortedArrayUsingSelector:@selector(compare:)];
|
||||||
|
|
||||||
|
NSArray *sortedFunctionAddresses = [[functionAddresses_ allObjects]
|
||||||
|
sortedArrayUsingSelector:@selector(compare:)];
|
||||||
|
|
||||||
|
// position ourselves at the 2nd function
|
||||||
|
unsigned int funcIndex = 1;
|
||||||
|
|
||||||
// Remove the dashes from the string
|
// Remove the dashes from the string
|
||||||
NSMutableString *compactedStr =
|
NSMutableString *compactedStr =
|
||||||
[NSMutableString stringWithCString:identifierStr encoding:NSASCIIStringEncoding];
|
[NSMutableString stringWithCString:identifierStr encoding:NSASCIIStringEncoding];
|
||||||
@ -733,7 +748,7 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
// The symbol reader doesn't want a trailing newline
|
// The symbol reader doesn't want a trailing newline
|
||||||
terminatingChar = '\0';
|
terminatingChar = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary *dict = [addresses_ objectForKey:address];
|
NSDictionary *dict = [addresses_ objectForKey:address];
|
||||||
NSNumber *line = [dict objectForKey:kAddressSourceLineKey];
|
NSNumber *line = [dict objectForKey:kAddressSourceLineKey];
|
||||||
NSString *symbol = [dict objectForKey:kAddressConvertedSymbolKey];
|
NSString *symbol = [dict objectForKey:kAddressConvertedSymbolKey];
|
||||||
@ -741,6 +756,15 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
symbol = [dict objectForKey:kAddressSymbolKey];
|
symbol = [dict objectForKey:kAddressSymbolKey];
|
||||||
|
|
||||||
|
// sanity check the function length by making sure it doesn't
|
||||||
|
// run beyond the next function entry
|
||||||
|
uint64_t nextFunctionAddress = 0;
|
||||||
|
if (symbol && funcIndex < [sortedFunctionAddresses count]) {
|
||||||
|
nextFunctionAddress = [[sortedFunctionAddresses objectAtIndex:funcIndex]
|
||||||
|
unsignedLongLongValue] - baseAddress;
|
||||||
|
++funcIndex;
|
||||||
|
}
|
||||||
|
|
||||||
// Skip some symbols
|
// Skip some symbols
|
||||||
if (StringHeadMatches(symbol, @"vtable for"))
|
if (StringHeadMatches(symbol, @"vtable for"))
|
||||||
continue;
|
continue;
|
||||||
@ -785,6 +809,16 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
if (line) {
|
if (line) {
|
||||||
if (symbol && functionLength) {
|
if (symbol && functionLength) {
|
||||||
uint64_t functionLengthVal = [functionLength unsignedLongLongValue];
|
uint64_t functionLengthVal = [functionLength unsignedLongLongValue];
|
||||||
|
|
||||||
|
// sanity check to make sure the length we were told does not exceed
|
||||||
|
// the space between this function and the next
|
||||||
|
if (nextFunctionAddress != 0) {
|
||||||
|
uint64_t functionLengthVal2 = nextFunctionAddress - addressVal;
|
||||||
|
|
||||||
|
if(functionLengthVal > functionLengthVal2 ) {
|
||||||
|
functionLengthVal = functionLengthVal2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
if (!WriteFormat(fd, "FUNC %llx %llx 0 %s\n", addressVal,
|
if (!WriteFormat(fd, "FUNC %llx %llx 0 %s\n", addressVal,
|
||||||
@ -824,10 +858,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track of last function start address on a per-section basis
|
|
||||||
if (!lastFunctionStartDict_)
|
|
||||||
lastFunctionStartDict_ = [[NSMutableDictionary alloc] init];
|
|
||||||
|
|
||||||
// If there's more than one, use the native one
|
// If there's more than one, use the native one
|
||||||
if ([headers_ count] > 1) {
|
if ([headers_ count] > 1) {
|
||||||
const NXArchInfo *localArchInfo = NXGetLocalArchInfo();
|
const NXArchInfo *localArchInfo = NXGetLocalArchInfo();
|
||||||
@ -863,10 +893,10 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
|
|||||||
[sourcePath_ release];
|
[sourcePath_ release];
|
||||||
[architecture_ release];
|
[architecture_ release];
|
||||||
[addresses_ release];
|
[addresses_ release];
|
||||||
|
[functionAddresses_ release];
|
||||||
[sources_ release];
|
[sources_ release];
|
||||||
[headers_ release];
|
[headers_ release];
|
||||||
[lastFunctionStartDict_ release];
|
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user