bug 465329 - sync to breakpad revision 303. r+a=bsmedberg
authorTed Mielczarek <ted.mielczarek@gmail.com>
Mon, 08 Dec 2008 12:04:33 -0500
changeset 22456 653f284051f6ee2d2ac0d6756f6fc3335c6d3b0d
parent 22455 55a4f47fcb1e306402c3de7f9bdb2cd832d7b7b6
child 22457 2385ebb971f8dc0d156bf72e65170d4f27463ea9
push id234
push usertmielczarek@mozilla.com
push dateMon, 22 Dec 2008 18:20:18 +0000
bugs465329
milestone1.9.1b3pre
bug 465329 - sync to breakpad revision 303. r+a=bsmedberg
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm
toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc
toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc
@@ -135,25 +135,32 @@ void ExceptionHandler::Initialize(const 
 
     // Set synchronization primitives and the handler thread.  Each
     // ExceptionHandler object gets its own handler thread because that's the
     // only way to reliably guarantee sufficient stack space in an exception,
     // and it allows an easy way to get a snapshot of the requesting thread's
     // context outside of an exception.
     InitializeCriticalSection(&handler_critical_section_);
     handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+    assert(handler_start_semaphore_ != NULL);
+
     handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+    assert(handler_finish_semaphore_ != NULL);
 
-    DWORD thread_id;
-    handler_thread_ = CreateThread(NULL,         // lpThreadAttributes
-                                   kExceptionHandlerThreadInitialStackSize,
-                                   ExceptionHandlerThreadMain,
-                                   this,         // lpParameter
-                                   0,            // dwCreationFlags
-                                   &thread_id);
+    // Don't attempt to create the thread if we could not create the semaphores.
+    if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) {
+      DWORD 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");
     if (dbghelp_module_) {
       minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>(
           GetProcAddress(dbghelp_module_, "MiniDumpWriteDump"));
     }
 
     // Load this library dynamically to not affect existing projects.  Most
@@ -259,16 +266,18 @@ ExceptionHandler::~ExceptionHandler() {
     CloseHandle(handler_finish_semaphore_);
   }
 }
 
 // static
 DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) {
   ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter);
   assert(self);
+  assert(self->handler_start_semaphore_ != NULL);
+  assert(self->handler_finish_semaphore_ != NULL);
 
   while (true) {
     if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) ==
         WAIT_OBJECT_0) {
       // Perform the requested action.
       self->handler_return_value_ = self->WriteMinidumpWithException(
           self->requesting_thread_id_, self->exception_info_, self->assertion_);
 
@@ -514,16 +523,27 @@ void ExceptionHandler::HandlePureVirtual
   // the behavior of "swallowing" exceptions.
   exit(0);
 }
 
 bool ExceptionHandler::WriteMinidumpOnHandlerThread(
     EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
   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.
   requesting_thread_id_ = GetCurrentThreadId();
   exception_info_ = exinfo;
   assertion_ = assertion;
 
   // This causes the handler thread to call WriteMinidumpWithException.
   ReleaseSemaphore(handler_start_semaphore_, 1, NULL);
 
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
@@ -41,17 +41,16 @@ typedef hash_map<string, dwarf2reader::S
 
 @interface DumpSymbols : NSObject {
  @protected
   NSString *sourcePath_;              // Source of symbols (STRONG)
   NSString *architecture_;            // Architecture to extract (STRONG)
   NSMutableDictionary *addresses_;    // Addresses and symbols (STRONG)
   NSMutableSet *functionAddresses_;   // Function addresses (STRONG)
   NSMutableDictionary *sources_;      // Address and Source file paths (STRONG)
-  NSMutableArray *cppAddresses_;      // Addresses of C++ symbols (STRONG)
   NSMutableDictionary *headers_;      // Mach-o header information (STRONG)
   NSMutableDictionary *sectionData_; // Keyed by seg/sect name (STRONG)
   uint32_t   lastStartAddress_;
   ArchSectionMap *sectionsForArch_;
 }
 
 - (id)initWithContentsOfFile:(NSString *)machoFile;
 
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm
@@ -58,17 +58,16 @@ static NSString *kAddressConvertedSymbol
 static NSString *kAddressSourceLineKey = @"line";
 static NSString *kFunctionSizeKey = @"size";
 static NSString *kFunctionFileKey = @"source_file";
 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 = @"???";
 
 // The section for __TEXT, __text seems to be always 1.  This is useful
 // for pruning out extraneous non-function symbols.
 static const int kTextSection = 1;
 
 namespace __gnu_cxx {
 template<> 
   struct hash<std::string> {
@@ -99,18 +98,17 @@ void DumpFunctionMap(const dwarf2reader:
 	     iter->second->lowpc,
 	     iter->second->highpc);
     }
   }
 }
 
 
 @interface DumpSymbols(PrivateMethods)
-- (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols;
-- (void)convertSymbols;
+- (NSString *)convertCPlusPlusSymbol:(NSString *)symbol;
 - (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section;
 - (BOOL)processSymbolItem:(struct nlist_64 *)list stringTable:(char *)table;
 - (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset;
 - (BOOL)loadSymbolInfo64:(void *)base offset:(uint32_t)offset;
 - (BOOL)loadSymbolInfoForArchitecture;
 - (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset;
 - (BOOL)loadSTABSSymbolInfo:(void *)base offset:(uint32_t)offset;
 - (void)generateSectionDictionary:(struct mach_header*)header;
@@ -121,107 +119,40 @@ void DumpFunctionMap(const dwarf2reader:
 - (void)processDWARFFunctionInfo:(dwarf2reader::FunctionMap*)address_to_funcinfo;
 - (void)processDWARFSourceFileInfo:(vector<dwarf2reader::SourceFileInfo>*) files;
 - (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset;
 - (dwarf2reader::SectionMap*)getSectionMapForArchitecture:(NSString*)architecture;
 @end
 
 @implementation DumpSymbols
 //=============================================================================
-- (NSArray *)convertCPlusPlusSymbols:(NSArray *)symbols {
-  NSMutableArray *symbols_demangled = [[NSMutableArray alloc]
-					initWithCapacity:[symbols count]];
+- (NSString *)convertCPlusPlusSymbol:(NSString *)symbol {
   // __cxa_demangle will realloc this if needed
   char *buffer = (char *)malloc(1024);
   size_t buffer_size = 1024;
   int result;
 
-  NSEnumerator *enumerator = [symbols objectEnumerator];
-  id symbolObject;
-  while ((symbolObject = [enumerator nextObject])) {
-    const char *symbol = [symbolObject UTF8String];
-    buffer = abi::__cxa_demangle(symbol, buffer, &buffer_size, &result);
-    if (result == 0) {
-      [symbols_demangled addObject:[NSString stringWithUTF8String:buffer]];
-    } else {
-      // unable to demangle - use mangled name instead
-      [symbols_demangled addObject:symbolObject];
-    }
+  const char *sym = [symbol UTF8String];
+  NSString *demangled = nil;
+  buffer = abi::__cxa_demangle(sym, buffer, &buffer_size, &result);
+  if (result == 0) {
+    demangled = [NSString stringWithUTF8String:buffer];
   }
   free(buffer);
-
-  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];
+  return demangled;
 }
 
 //=============================================================================
 - (void)addFunction:(NSString *)name line:(int)line address:(uint64_t)address section:(int)section {
   NSNumber *addressNum = [NSNumber numberWithUnsignedLongLong:address];
 
   if (!address)
     return;
 
-  // If the function starts with "_Z" or "__Z" then add it to the list of
-  // addresses to run through the c++filt
+  // If the function starts with "_Z" or "__Z" then demangle it.
   BOOL isCPP = NO;
 
   if ([name hasPrefix:@"__Z"]) {
     // Remove the leading underscore
     name = [name substringFromIndex:1];
     isCPP = YES;
   } else if ([name hasPrefix:@"_Z"]) {
     isCPP = YES;
@@ -250,22 +181,16 @@ void DumpFunctionMap(const dwarf2reader:
     // 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 (!cppAddresses_)
-      cppAddresses_ = [[NSMutableArray alloc] init];
-    [cppAddresses_ addObject:addressNum];
   } else if ([name characterAtIndex:0] == '_') {
     // Remove the leading underscore
     name = [name substringFromIndex:1];
   }
 
   // If there's already an entry for this address, check and see if we can add
   // either the symbol, or a missing line #
   NSMutableDictionary *dict = [addresses_ objectForKey:addressNum];
@@ -277,16 +202,23 @@ void DumpFunctionMap(const dwarf2reader:
   }
 
   if (name && ![dict objectForKey:kAddressSymbolKey]) {
     [dict setObject:name forKey:kAddressSymbolKey];
 
     // only functions, not line number addresses
     [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])
     [dict setObject:[NSNumber numberWithUnsignedInt:line]
              forKey:kAddressSourceLineKey];
 
 }
 
 //=============================================================================
@@ -495,16 +427,25 @@ void DumpFunctionMap(const dwarf2reader:
       [dict release];
     }
 
     // set name of function if it isn't already set
     if (![dict objectForKey:kAddressSymbolKey]) {
       NSString *symbolName = [NSString stringWithUTF8String:iter->second->name.c_str()];
       [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
     if (iter->second->line && ![dict objectForKey:kAddressSourceLineKey])
       [dict setObject:[NSNumber numberWithUnsignedInt:iter->second->line]
 	    forKey:kAddressSourceLineKey];
 
     // set function size by subtracting low PC from high PC
     if (![dict objectForKey:kFunctionSizeKey]) {
@@ -915,17 +856,16 @@ static BOOL WriteFormat(int fd, const ch
   }
 
   // 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
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc
@@ -46,16 +46,35 @@ namespace __gnu_cxx
     {
       size_t operator()(const std::string& k) const;
     };
 }
 
 
 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,
                                      vector<string>* dirs,
                                      LineMap* linemap):linemap_(linemap),
                                                        files_(files),
                                                        dirs_(dirs) {
   // The dirs and files are 1 indexed, so just make sure we put
   // nothing in the 0 vector.
   assert(dirs->size() == 0);
@@ -112,16 +131,17 @@ void CULineInfoHandler::AddLine(uint64 a
   }
 }
 
 bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
                                                  uint8 address_size,
                                                  uint8 offset_size,
                                                  uint64 cu_length,
                                                  uint8 dwarf_version) {
+  current_compilation_unit_offset_ = offset;
   return true;
 }
 
 
 // For function info, we only care about subprograms and inlined
 // subroutines. For line info, the DW_AT_stmt_list lives in the
 // compile unit tag.
 
@@ -147,18 +167,22 @@ bool CUFunctionInfoHandler::StartDIE(uin
 }
 
 // Only care about the name attribute for functions
 
 void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
                                                    enum DwarfAttribute attr,
                                                    enum DwarfForm form,
                                                    const string &data) {
-  if (attr == DW_AT_name && current_function_info_)
-    current_function_info_->name = data;
+  if (current_function_info_) {
+    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,
                                                      enum DwarfAttribute attr,
                                                      enum DwarfForm form,
                                                      uint64 data) {
   if (attr == DW_AT_stmt_list) {
     SectionMap::const_iterator iter = sections_.find("__debug_line");
@@ -178,16 +202,34 @@ void CUFunctionInfoHandler::ProcessAttri
         current_function_info_->highpc = data;
         break;
       case DW_AT_decl_line:
         current_function_info_->line = data;
         break;
       case DW_AT_decl_file:
         current_function_info_->file = files_->at(data).name;
         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:
         break;
     }
   }
 }
 
 void CUFunctionInfoHandler::EndDIE(uint64 offset) {
   if (current_function_info_ && current_function_info_->lowpc)
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h
@@ -42,16 +42,18 @@
 #include "common/mac/dwarf/dwarf2reader.h"
 
 
 namespace dwarf2reader {
 
 struct FunctionInfo {
   // Name of the function
   string name;
+  // Mangled name of the function
+  string mangled_name;
   // File containing this function
   string file;
   // Line number for start of function.
   uint32 line;
   // Beginning address for this function
   uint64 lowpc;
   // End address for this function.
   uint64 highpc;
@@ -164,12 +166,13 @@ class CUFunctionInfoHandler: public Dwar
   vector<string>* dirs_;
   LineMap* linemap_;
   FunctionMap* offset_to_funcinfo_;
   FunctionMap* address_to_funcinfo_;
   CULineInfoHandler* linehandler_;
   const SectionMap& sections_;
   ByteReader* reader_;
   FunctionInfo* current_function_info_;
+  uint64 current_compilation_unit_offset_;
 };
 
 }  // namespace dwarf2reader
 #endif  // COMMON_MAC_DWARF_FUNCTIONINFO_H__