From 026b28ec403735378ed77d07e633c40a08eab4c4 Mon Sep 17 00:00:00 2001 From: ladderbreaker Date: Tue, 22 May 2007 00:25:38 +0000 Subject: [PATCH] issue 167: reviewed by Benjamin Smedberg git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@174 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/mac/handler/minidump_generator.cc | 128 ++++++++++++++----- 1 file changed, 96 insertions(+), 32 deletions(-) diff --git a/src/client/mac/handler/minidump_generator.cc b/src/client/mac/handler/minidump_generator.cc index 11a770ee..f6d1811d 100644 --- a/src/client/mac/handler/minidump_generator.cc +++ b/src/client/mac/handler/minidump_generator.cc @@ -47,28 +47,36 @@ using MacStringUtils::ConvertToString; using MacStringUtils::IntegerValueAtIndex; namespace google_breakpad { - + +// constructor when generating from within the crashed process MinidumpGenerator::MinidumpGenerator() : exception_type_(0), exception_code_(0), exception_thread_(0), crashing_task_(mach_task_self()), - handler_thread_(mach_thread_self()) { - dynamic_images_ = new DynamicImages(mach_task_self()); + handler_thread_(mach_thread_self()), + dynamic_images_(NULL) { GatherSystemInformation(); } +// constructor when generating from a different process than the crashed process MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread) : exception_type_(0), exception_code_(0), exception_thread_(0), crashing_task_(crashing_task), handler_thread_(handler_thread) { - dynamic_images_ = new DynamicImages(crashing_task_); + if (crashing_task != mach_task_self()) { + dynamic_images_ = new DynamicImages(crashing_task_); + } else { + dynamic_images_ = NULL; + } + GatherSystemInformation(); } MinidumpGenerator::~MinidumpGenerator() { + delete dynamic_images_; } char MinidumpGenerator::build_string_[16]; @@ -240,12 +248,14 @@ bool MinidumpGenerator::WriteStackFromStartAddress( if (!memory.Allocate(size)) return false; - void *stack_memory = ReadTaskMemory(crashing_task_, (void*)start_addr, size); - - bool result = memory.Copy(stack_memory, size); - - free(stack_memory); - + bool result; + if (dynamic_images_) { + void *stack_memory = ReadTaskMemory(crashing_task_, (void*)start_addr, size); + result = memory.Copy(stack_memory, size); + free(stack_memory); + } else { + result = memory.Copy(reinterpret_cast(start_addr), size); + } stack_location->start_of_memory_range = start_addr; stack_location->memory = memory.location(); @@ -547,42 +557,95 @@ bool MinidumpGenerator::WriteSystemInfoStream( bool MinidumpGenerator::WriteModuleStream(unsigned int index, MDRawModule *module) { - DynamicImage *image = dynamic_images_->GetImage(index); + if (dynamic_images_) { + // we're in a different process than the crashed process + DynamicImage *image = dynamic_images_->GetImage(index); - if (!image) - return false; + if (!image) + return false; - const mach_header *header = image->GetMachHeader(); + const mach_header *header = image->GetMachHeader(); - if (!header) - return false; + if (!header) + return false; - int cpu_type = header->cputype; + int cpu_type = header->cputype; - memset(module, 0, sizeof(MDRawModule)); + memset(module, 0, sizeof(MDRawModule)); - MDLocationDescriptor string_location; + MDLocationDescriptor string_location; - const char* name = image->GetFilePath(); - if (!writer_.WriteString(name, 0, &string_location)) - return false; + const char* name = image->GetFilePath(); + if (!writer_.WriteString(name, 0, &string_location)) + return false; - module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide(); - module->size_of_image = image->GetVMSize(); - module->module_name_rva = string_location.rva; + module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide(); + module->size_of_image = image->GetVMSize(); + module->module_name_rva = string_location.rva; - if (!WriteCVRecord(module, cpu_type, name)) { - return false; + if (!WriteCVRecord(module, cpu_type, name)) { + return false; + } + } else { + // we're getting module info in the crashed process + const struct mach_header *header = _dyld_get_image_header(index); + + if (!header) + return false; + + int cpu_type = header->cputype; + unsigned long slide = _dyld_get_image_vmaddr_slide(index); + const char* name = _dyld_get_image_name(index); + const struct load_command *cmd = + reinterpret_cast(header + 1); + + memset(module, 0, sizeof(MDRawModule)); + + for (unsigned int i = 0; cmd && (i < header->ncmds); i++) { + if (cmd->cmd == LC_SEGMENT) { + const struct segment_command *seg = + reinterpret_cast(cmd); + if (!strcmp(seg->segname, "__TEXT")) { + MDLocationDescriptor string_location; + + if (!writer_.WriteString(name, 0, &string_location)) + return false; + + module->base_of_image = seg->vmaddr + slide; + module->size_of_image = seg->vmsize; + module->module_name_rva = string_location.rva; + + if (!WriteCVRecord(module, cpu_type, name)) + return false; + + return true; + } + } + + cmd = reinterpret_cast((char *)cmd + cmd->cmdsize); + } } - + return true; } int MinidumpGenerator::FindExecutableModule() { - int index = dynamic_images_->GetExecutableImageIndex(); + if (dynamic_images_) { + int index = dynamic_images_->GetExecutableImageIndex(); - if (index >= 0) { - return index; + if (index >= 0) { + return index; + } + } else { + int image_count = _dyld_image_count(); + const struct mach_header *header; + + for (int index = 0; index < image_count; ++index) { + header = _dyld_get_image_header(index); + + if (header->filetype == MH_EXECUTE) + return index; + } } // failed - just use the first image @@ -645,7 +708,8 @@ bool MinidumpGenerator::WriteModuleListStream( if (!_dyld_present()) return false; - int image_count = dynamic_images_->GetImageCount(); + int image_count = dynamic_images_ ? + dynamic_images_->GetImageCount() : _dyld_image_count(); if (!list.AllocateObjectAndArray(image_count, MD_MODULE_SIZE)) return false;