зеркало из https://github.com/mozilla/pjs.git
bug 465329 - sync to breakpad revision 303. r=bsmedberg
This commit is contained in:
Родитель
29020dc41d
Коммит
4ff4cd03f2
|
@ -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];
|
||||||
|
@ -282,6 +207,13 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
|
||||||
// only functions, not line number addresses
|
// only functions, not line number addresses
|
||||||
[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]
|
||||||
|
@ -500,6 +432,15 @@ void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) {
|
||||||
NSString *symbolName = [NSString stringWithUTF8String:iter->second->name.c_str()];
|
NSString *symbolName = [NSString stringWithUTF8String:iter->second->name.c_str()];
|
||||||
[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])
|
||||||
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче