bug 465329 - sync to breakpad revision 303. r=bsmedberg

This commit is contained in:
Ted Mielczarek 2008-12-08 12:04:33 -05:00
Родитель 29020dc41d
Коммит 4ff4cd03f2
5 изменённых файлов: 100 добавлений и 96 удалений

Просмотреть файл

@ -140,15 +140,22 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
// context outside of an exception. // context outside of an exception.
InitializeCriticalSection(&handler_critical_section_); InitializeCriticalSection(&handler_critical_section_);
handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); assert(handler_start_semaphore_ != NULL);
DWORD thread_id; handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
handler_thread_ = CreateThread(NULL, // lpThreadAttributes assert(handler_finish_semaphore_ != NULL);
kExceptionHandlerThreadInitialStackSize,
ExceptionHandlerThreadMain, // Don't attempt to create the thread if we could not create the semaphores.
this, // lpParameter if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) {
0, // dwCreationFlags DWORD thread_id;
&thread_id); handler_thread_ = CreateThread(NULL, // lpThreadAttributes
kExceptionHandlerThreadInitialStackSize,
ExceptionHandlerThreadMain,
this, // lpParameter
0, // dwCreationFlags
&thread_id);
assert(handler_thread_ != NULL);
}
dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); dbghelp_module_ = LoadLibrary(L"dbghelp.dll");
if (dbghelp_module_) { if (dbghelp_module_) {
@ -264,6 +271,8 @@ ExceptionHandler::~ExceptionHandler() {
DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) {
ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter); ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter);
assert(self); assert(self);
assert(self->handler_start_semaphore_ != NULL);
assert(self->handler_finish_semaphore_ != NULL);
while (true) { while (true) {
if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) ==
@ -519,6 +528,17 @@ bool ExceptionHandler::WriteMinidumpOnHandlerThread(
EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
EnterCriticalSection(&handler_critical_section_); EnterCriticalSection(&handler_critical_section_);
// There isn't much we can do if the handler thread
// was not successfully created.
if (handler_thread_ == NULL) {
LeaveCriticalSection(&handler_critical_section_);
return false;
}
// The handler thread should only be created when the semaphores are valid.
assert(handler_start_semaphore_ != NULL);
assert(handler_finish_semaphore_ != NULL);
// Set up data to be passed in to the handler thread. // Set up data to be passed in to the handler thread.
requesting_thread_id_ = GetCurrentThreadId(); requesting_thread_id_ = GetCurrentThreadId();
exception_info_ = exinfo; exception_info_ = exinfo;

Просмотреть файл

@ -46,7 +46,6 @@ typedef hash_map<string, dwarf2reader::SectionMap *> ArchSectionMap;
NSMutableDictionary *addresses_; // Addresses and symbols (STRONG) NSMutableDictionary *addresses_; // Addresses and symbols (STRONG)
NSMutableSet *functionAddresses_; // Function addresses (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)
NSMutableDictionary *headers_; // Mach-o header information (STRONG) NSMutableDictionary *headers_; // Mach-o header information (STRONG)
NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG) NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG)
uint32_t lastStartAddress_; uint32_t lastStartAddress_;

Просмотреть файл

@ -63,7 +63,6 @@ static NSString *kHeaderSizeKey = @"size";
static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header
static NSString *kHeaderIs64BitKey = @"is64"; static NSString *kHeaderIs64BitKey = @"is64";
static NSString *kHeaderCPUTypeKey = @"cpuType"; static NSString *kHeaderCPUTypeKey = @"cpuType";
static NSString *kUnknownSymbol = @"???";
// The section for __TEXT, __text seems to be always 1. This is useful // The section for __TEXT, __text seems to be always 1. This is useful
// for pruning out extraneous non-function symbols. // for pruning out extraneous non-function symbols.
@ -104,8 +103,7 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
@interface DumpSymbols(PrivateMethods) @interface DumpSymbols(PrivateMethods)
- (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols; - (NSString *)convertCPlusPlusSymbol:(NSString *)symbol;
- (void)convertSymbols;
- (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section; - (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section;
- (BOOL)processSymbolItem:(struct nlist_64 *)list stringTable:(char *)table; - (BOOL)processSymbolItem:(struct nlist_64 *)list stringTable:(char *)table;
- (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset; - (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset;
@ -126,86 +124,20 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
@implementation DumpSymbols @implementation DumpSymbols
//============================================================================= //=============================================================================
- (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols { - (NSString *)convertCPlusPlusSymbol:(NSString *)symbol {
NSMutableArray *symbols_demangled = [[NSMutableArray alloc]
initWithCapacity:[symbols count]];
// __cxa_demangle will realloc this if needed // __cxa_demangle will realloc this if needed
char *buffer = (char *)malloc(1024); char *buffer = (char *)malloc(1024);
size_t buffer_size = 1024; size_t buffer_size = 1024;
int result; int result;
NSEnumerator *enumerator = [symbols objectEnumerator]; const char *sym = [symbol UTF8String];
id symbolObject; NSString *demangled = nil;
while ((symbolObject = [enumerator nextObject])) { buffer = abi::__cxa_demangle(sym, buffer, &buffer_size, &result);
const char *symbol = [symbolObject UTF8String]; if (result == 0) {
buffer = abi::__cxa_demangle(symbol, buffer, &buffer_size, &result); demangled = [NSString stringWithUTF8String:buffer];
if (result == 0) {
[symbols_demangled addObject:[NSString stringWithUTF8String:buffer]];
} else {
// unable to demangle - use mangled name instead
[symbols_demangled addObject:symbolObject];
}
} }
free(buffer); free(buffer);
return demangled;
return symbols_demangled;
}
//=============================================================================
- (void)convertSymbols {
unsigned int count = [cppAddresses_ count];
NSMutableArray *symbols = [[NSMutableArray alloc] initWithCapacity:count];
// Sort addresses for processing
NSArray *addresses = [cppAddresses_ sortedArrayUsingSelector:
@selector(compare:)];
for (unsigned int i = 0; i < count; ++i) {
NSMutableDictionary *dict = [addresses_ objectForKey:
[addresses objectAtIndex:i]];
NSString *symbol = [dict objectForKey:kAddressSymbolKey];
// Make sure that the symbol is valid
if ([symbol length] < 1)
symbol = kUnknownSymbol;
[symbols addObject:symbol];
}
// In order to deal with crashing problems in c++filt, we setup
// a while loop to handle the case where convertCPlusPlusSymbols
// only returns partial results.
// We then attempt to continue from the point where c++filt failed
// and add the partial results to the total results until we're
// completely done.
unsigned int totalIndex = 0;
unsigned int totalCount = count;
while (totalIndex < totalCount) {
NSRange range = NSMakeRange(totalIndex, totalCount - totalIndex);
NSArray *subarray = [symbols subarrayWithRange:range];
NSArray *converted = [self convertCPlusPlusSymbols:subarray];
unsigned int convertedCount = [converted count];
if (convertedCount == 0) {
break; // we give up at this point
}
for (unsigned int convertedIndex = 0;
convertedIndex < convertedCount && totalIndex < totalCount;
++totalIndex, ++convertedIndex) {
NSMutableDictionary *dict = [addresses_ objectForKey:
[addresses objectAtIndex:totalIndex]];
NSString *symbol = [converted objectAtIndex:convertedIndex];
// Only add if this is a non-zero length symbol
if ([symbol length])
[dict setObject:symbol forKey:kAddressConvertedSymbolKey];
}
}
[symbols release];
} }
//============================================================================= //=============================================================================
@ -215,8 +147,7 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
if (!address) if (!address)
return; return;
// If the function starts with "_Z" or "__Z" then add it to the list of // If the function starts with "_Z" or "__Z" then demangle it.
// addresses to run through the c++filt
BOOL isCPP = NO; BOOL isCPP = NO;
if ([name hasPrefix:@"__Z"]) { if ([name hasPrefix:@"__Z"]) {
@ -255,12 +186,6 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
NSRange emptyRange = { NSNotFound, 0 }; NSRange emptyRange = { NSNotFound, 0 };
NSRange objcppRange = [name rangeOfCharacterFromSet:objcppCharSet]; NSRange objcppRange = [name rangeOfCharacterFromSet:objcppCharSet];
isCPP = NSEqualRanges(objcppRange, emptyRange); isCPP = NSEqualRanges(objcppRange, emptyRange);
}
if (isCPP) {
if (!cppAddresses_)
cppAddresses_ = [[NSMutableArray alloc] init];
[cppAddresses_ addObject:addressNum];
} else if ([name characterAtIndex:0] == '_') { } else if ([name characterAtIndex:0] == '_') {
// Remove the leading underscore // Remove the leading underscore
name = [name substringFromIndex:1]; name = [name substringFromIndex:1];
@ -283,6 +208,13 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
[functionAddresses_ addObject:addressNum]; [functionAddresses_ addObject:addressNum];
} }
if (isCPP) {
// try demangling
NSString *demangled = [self convertCPlusPlusSymbol:name];
if (demangled != nil)
[dict setObject:demangled forKey:kAddressConvertedSymbolKey];
}
if (line && ![dict objectForKey:kAddressSourceLineKey]) if (line && ![dict objectForKey:kAddressSourceLineKey])
[dict setObject:[NSNumber numberWithUnsignedInt:line] [dict setObject:[NSNumber numberWithUnsignedInt:line]
forKey:kAddressSourceLineKey]; forKey:kAddressSourceLineKey];
@ -501,6 +433,15 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
[dict setObject:symbolName forKey:kAddressSymbolKey]; [dict setObject:symbolName forKey:kAddressSymbolKey];
} }
// try demangling function name if we have a mangled name
if (![dict objectForKey:kAddressConvertedSymbolKey] &&
!iter->second->mangled_name.empty()) {
NSString *mangled = [NSString stringWithUTF8String:iter->second->mangled_name.c_str()];
NSString *demangled = [self convertCPlusPlusSymbol:mangled];
if (demangled != nil)
[dict setObject:demangled forKey:kAddressConvertedSymbolKey];
}
// set line number for beginning of function // set line number for beginning of function
if (iter->second->line && ![dict objectForKey:kAddressSourceLineKey]) if (iter->second->line && ![dict objectForKey:kAddressSourceLineKey])
[dict setObject:[NSNumber numberWithUnsignedInt:iter->second->line] [dict setObject:[NSNumber numberWithUnsignedInt:iter->second->line]
@ -920,7 +861,6 @@ static BOOL WriteFormat(int fd, const char *fmt, ...) {
// Gather the information // Gather the information
[self loadSymbolInfoForArchitecture]; [self loadSymbolInfoForArchitecture];
[self convertSymbols];
NSArray *sortedAddresses = [[addresses_ allKeys] NSArray *sortedAddresses = [[addresses_ allKeys]
sortedArrayUsingSelector:@selector(compare:)]; sortedArrayUsingSelector:@selector(compare:)];

Просмотреть файл

@ -51,6 +51,25 @@ namespace __gnu_cxx
namespace dwarf2reader { namespace dwarf2reader {
// Given an offset value, its form, and the base offset of the
// compilation unit containing this value, return an absolute offset
// within the .debug_info section.
uint64 GetAbsoluteOffset(uint64 offset,
enum DwarfForm form,
uint64 compilation_unit_base) {
switch (form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
return offset + compilation_unit_base;
case DW_FORM_ref_addr:
default:
return offset;
}
}
CULineInfoHandler::CULineInfoHandler(vector<SourceFileInfo>* files, CULineInfoHandler::CULineInfoHandler(vector<SourceFileInfo>* files,
vector<string>* dirs, vector<string>* dirs,
LineMap* linemap):linemap_(linemap), LineMap* linemap):linemap_(linemap),
@ -117,6 +136,7 @@ bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
uint8 offset_size, uint8 offset_size,
uint64 cu_length, uint64 cu_length,
uint8 dwarf_version) { uint8 dwarf_version) {
current_compilation_unit_offset_ = offset;
return true; return true;
} }
@ -152,8 +172,12 @@ void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
enum DwarfAttribute attr, enum DwarfAttribute attr,
enum DwarfForm form, enum DwarfForm form,
const string &data) { const string &data) {
if (attr == DW_AT_name && current_function_info_) if (current_function_info_) {
current_function_info_->name = data; if (attr == DW_AT_name)
current_function_info_->name = data;
else if(attr == DW_AT_MIPS_linkage_name)
current_function_info_->mangled_name = data;
}
} }
void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
@ -183,6 +207,24 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
case DW_AT_decl_file: case DW_AT_decl_file:
current_function_info_->file = files_->at(data).name; current_function_info_->file = files_->at(data).name;
break; break;
case DW_AT_specification: {
// Some functions have a "specification" attribute
// which means they were defined elsewhere. The name
// attribute is not repeated, and must be taken from
// the specification DIE. Here we'll assume that
// any DIE referenced in this manner will already have
// been seen, but that's not really required by the spec.
uint64 abs_offset = GetAbsoluteOffset(data, form, current_compilation_unit_offset_);
FunctionMap::iterator iter = offset_to_funcinfo_->find(abs_offset);
if (iter != offset_to_funcinfo_->end()) {
current_function_info_->name = iter->second->name;
current_function_info_->mangled_name = iter->second->mangled_name;
} else {
// If you hit this, this code probably needs to be rewritten.
fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", abs_offset, offset);
}
break;
}
default: default:
break; break;
} }

Просмотреть файл

@ -47,6 +47,8 @@ namespace dwarf2reader {
struct FunctionInfo { struct FunctionInfo {
// Name of the function // Name of the function
string name; string name;
// Mangled name of the function
string mangled_name;
// File containing this function // File containing this function
string file; string file;
// Line number for start of function. // Line number for start of function.
@ -169,6 +171,7 @@ class CUFunctionInfoHandler: public Dwarf2Handler {
const SectionMap& sections_; const SectionMap& sections_;
ByteReader* reader_; ByteReader* reader_;
FunctionInfo* current_function_info_; FunctionInfo* current_function_info_;
uint64 current_compilation_unit_offset_;
}; };
} // namespace dwarf2reader } // namespace dwarf2reader