c++filt crashes when fed some mangled ObjC++ names. Oops. Patch by Dave

MacLachlan, r=me.


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@145 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mmentovai 2007-04-12 20:40:22 +00:00
parent e9017f3239
commit 1d4ce0a1d8

View file

@ -77,26 +77,6 @@ static const int kTextSection = 1;
- (BOOL)loadModuleInfo; - (BOOL)loadModuleInfo;
@end @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 @implementation DumpSymbols
//============================================================================= //=============================================================================
- (NSString *)stringFromTask:(NSString *)action args:(NSArray *)args - (NSString *)stringFromTask:(NSString *)action args:(NSArray *)args
@ -164,13 +144,13 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
// Unfortunately, c++filt doesn't take a file containing names, so we'll // Unfortunately, c++filt doesn't take a file containing names, so we'll
// copy the symbols to a temporary file and use that as stdin. // copy the symbols to a temporary file and use that as stdin.
char buffer[PATH_MAX]; char buffer[PATH_MAX];
snprintf(buffer, sizeof(buffer), "/tmp/dump_syms_filtXXXXX"); strlcpy(buffer, "/tmp/dump_syms_filtXXXXX", sizeof(buffer));
int fd = mkstemp(buffer); int fd = mkstemp(buffer);
char nl = '\n';
for (unsigned int i = 0; i < count; ++i) { for (unsigned int i = 0; i < count; ++i) {
const char *symbol = [[symbols objectAtIndex:i] UTF8String]; const char *symbol = [[symbols objectAtIndex:i] UTF8String];
write(fd, symbol, strlen(symbol)); write(fd, symbol, strlen(symbol));
write(fd, &nl, 1); write(fd, "\n", 1);
} }
// Reset to the beginning and wrap up with a file handle // Reset to the beginning and wrap up with a file handle
@ -254,24 +234,44 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
// addresses to run through the c++filt // addresses to run through the c++filt
BOOL isCPP = NO; BOOL isCPP = NO;
if (StringHeadMatches(name, @"__Z")) { if ([name hasPrefix:@"__Z"]) {
// Remove the leading underscore // Remove the leading underscore
name = [name substringFromIndex:1]; name = [name substringFromIndex:1];
isCPP = YES; isCPP = YES;
} else if (StringHeadMatches(name, @"_Z")) { } else if ([name hasPrefix:@"_Z"]) {
isCPP = YES; isCPP = YES;
} }
// Filter out non-functions // Filter out non-functions
if (StringTailMatches(name, @".eh")) if ([name hasSuffix:@".eh"])
return; return;
if (StringTailMatches(name, @"__func__")) if ([name hasSuffix:@"__func__"])
return; return;
if (StringTailMatches(name, @"GCC_except_table")) if ([name hasSuffix:@"GCC_except_table"])
return; return;
if (isCPP) {
// OBJCPP_MANGLING_HACK
// There are cases where ObjC++ mangles up an ObjC name using quasi-C++
// mangling:
// @implementation Foozles + (void)barzles {
// static int Baz = 0;
// } @end
// gives you _ZZ18+[Foozles barzles]E3Baz
// c++filt won't parse this properly, and will crash in certain cases.
// Logged as radar:
// 5129938: c++filt does not deal with ObjC++ symbols
// If 5129938 ever gets fixed, we can remove this, but for now this prevents
// c++filt from attempting to demangle names it doesn't know how to handle.
// This is with c++filt 2.16
NSCharacterSet *objcppCharSet = [NSCharacterSet characterSetWithCharactersInString:@"-+[]: "];
NSRange emptyRange = { NSNotFound, 0 };
NSRange objcppRange = [name rangeOfCharacterFromSet:objcppCharSet];
isCPP = NSEqualRanges(objcppRange, emptyRange);
}
if (isCPP) { if (isCPP) {
if (!cppAddresses_) if (!cppAddresses_)
cppAddresses_ = [[NSMutableArray alloc] init]; cppAddresses_ = [[NSMutableArray alloc] init];
@ -321,7 +321,7 @@ static BOOL StringTailMatches(NSString *str, NSString *tail) {
// an N_FUN from section 0 may follow the initial N_FUN // an N_FUN from section 0 may follow the initial N_FUN
// giving us function length information // giving us function length information
NSMutableDictionary *dict = [addresses_ objectForKey: NSMutableDictionary *dict = [addresses_ objectForKey:
[NSNumber numberWithUnsignedLong:lastStartAddress_] ]; [NSNumber numberWithUnsignedLong:lastStartAddress_]];
assert(dict); assert(dict);
@ -788,28 +788,28 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
} }
// Skip some symbols // Skip some symbols
if (StringHeadMatches(symbol, @"vtable for")) if ([symbol hasPrefix:@"vtable for"])
continue; continue;
if (StringHeadMatches(symbol, @"__static_initialization_and_destruction_0")) if ([symbol hasPrefix:@"__static_initialization_and_destruction_0"])
continue; continue;
if (StringHeadMatches(symbol, @"_GLOBAL__I__")) if ([symbol hasPrefix:@"_GLOBAL__I__"])
continue; continue;
if (StringHeadMatches(symbol, @"__func__.")) if ([symbol hasPrefix:@"__func__."])
continue; continue;
if (StringHeadMatches(symbol, @"__gnu")) if ([symbol hasPrefix:@"__gnu"])
continue; continue;
if (StringHeadMatches(symbol, @"typeinfo ")) if ([symbol hasPrefix:@"typeinfo "])
continue; continue;
if (StringHeadMatches(symbol, @"EH_frame")) if ([symbol hasPrefix:@"EH_frame"])
continue; continue;
if (StringHeadMatches(symbol, @"GCC_except_table")) if ([symbol hasPrefix:@"GCC_except_table"])
continue; continue;
// Find the source file (if any) that contains this address // Find the source file (if any) that contains this address