mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-01-02 04:34:47 +01:00
Allow out-of-process minidump generation to work on processes of a different CPU architecture
R=mark at http://breakpad.appspot.com/241001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@746 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
0d9bd40775
commit
0344a368de
10 changed files with 1262 additions and 653 deletions
|
|
@ -31,7 +31,9 @@
|
|||
#include <cstdio>
|
||||
|
||||
#include <mach/host_info.h>
|
||||
#include <mach/i386/thread_status.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include <mach/ppc/thread_status.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/loader.h>
|
||||
|
|
@ -65,6 +67,7 @@ MinidumpGenerator::MinidumpGenerator()
|
|||
exception_thread_(0),
|
||||
crashing_task_(mach_task_self()),
|
||||
handler_thread_(mach_thread_self()),
|
||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||
dynamic_images_(NULL),
|
||||
memory_blocks_(&allocator_) {
|
||||
GatherSystemInformation();
|
||||
|
|
@ -81,12 +84,15 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
|
|||
exception_thread_(0),
|
||||
crashing_task_(crashing_task),
|
||||
handler_thread_(handler_thread),
|
||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||
dynamic_images_(NULL),
|
||||
memory_blocks_(&allocator_) {
|
||||
if (crashing_task != mach_task_self()) {
|
||||
dynamic_images_ = new DynamicImages(crashing_task_);
|
||||
cpu_type_ = dynamic_images_->GetCPUType();
|
||||
} else {
|
||||
dynamic_images_ = NULL;
|
||||
cpu_type_ = DynamicImages::GetNativeCPUType();
|
||||
}
|
||||
|
||||
GatherSystemInformation();
|
||||
|
|
@ -254,8 +260,10 @@ size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK) {
|
||||
if (((cpu_type_ & CPU_ARCH_ABI64) &&
|
||||
(stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_64BIT) ||
|
||||
(!(cpu_type_ & CPU_ARCH_ABI64) &&
|
||||
(stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_32BIT)) {
|
||||
// The stack for thread 0 needs to extend all the way to
|
||||
// 0xc0000000 on 32 bit and 00007fff5fc00000 on 64bit. HOWEVER,
|
||||
// for many processes, the stack is first created in one page
|
||||
|
|
@ -305,20 +313,15 @@ bool MinidumpGenerator::WriteStackFromStartAddress(
|
|||
return false;
|
||||
|
||||
if (dynamic_images_) {
|
||||
|
||||
kern_return_t kr;
|
||||
|
||||
void *stack_memory = ReadTaskMemory(crashing_task_,
|
||||
(void*)start_addr,
|
||||
size,
|
||||
&kr);
|
||||
|
||||
if (stack_memory == NULL) {
|
||||
vector<uint8_t> stack_memory;
|
||||
if (ReadTaskMemory(crashing_task_,
|
||||
start_addr,
|
||||
size,
|
||||
stack_memory) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = memory.Copy(stack_memory, size);
|
||||
free(stack_memory);
|
||||
result = memory.Copy(&stack_memory[0], size);
|
||||
} else {
|
||||
result = memory.Copy(reinterpret_cast<const void *>(start_addr), size);
|
||||
}
|
||||
|
|
@ -330,34 +333,99 @@ bool MinidumpGenerator::WriteStackFromStartAddress(
|
|||
return result;
|
||||
}
|
||||
|
||||
#if TARGET_CPU_PPC || TARGET_CPU_PPC64
|
||||
bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
switch (cpu_type_) {
|
||||
case CPU_TYPE_POWERPC:
|
||||
return WriteStackPPC(state, stack_location);
|
||||
case CPU_TYPE_POWERPC64:
|
||||
return WriteStackPPC64(state, stack_location);
|
||||
case CPU_TYPE_I386:
|
||||
return WriteStackX86(state, stack_location);
|
||||
case CPU_TYPE_X86_64:
|
||||
return WriteStackX86_64(state, stack_location);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location) {
|
||||
switch (cpu_type_) {
|
||||
case CPU_TYPE_POWERPC:
|
||||
return WriteContextPPC(state, register_location);
|
||||
case CPU_TYPE_POWERPC64:
|
||||
return WriteContextPPC64(state, register_location);
|
||||
case CPU_TYPE_I386:
|
||||
return WriteContextX86(state, register_location);
|
||||
case CPU_TYPE_X86_64:
|
||||
return WriteContextX86_64(state, register_location);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
u_int64_t MinidumpGenerator::CurrentPCForStack(
|
||||
breakpad_thread_state_data_t state) {
|
||||
switch (cpu_type_) {
|
||||
case CPU_TYPE_POWERPC:
|
||||
return CurrentPCForStackPPC(state);
|
||||
case CPU_TYPE_POWERPC64:
|
||||
return CurrentPCForStackPPC64(state);
|
||||
case CPU_TYPE_I386:
|
||||
return CurrentPCForStackX86(state);
|
||||
case CPU_TYPE_X86_64:
|
||||
return CurrentPCForStackX86_64(state);
|
||||
default:
|
||||
assert("Unknown CPU type!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
ppc_thread_state_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state_t *>(state);
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
|
||||
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
ppc_thread_state64_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state64_t *>(state);
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
|
||||
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
MinidumpGenerator::CurrentPCForStackPPC(breakpad_thread_state_data_t state) {
|
||||
ppc_thread_state_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state_t *>(state);
|
||||
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, srr0);
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MinidumpContext> context(&writer_);
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
u_int64_t
|
||||
MinidumpGenerator::CurrentPCForStackPPC64(breakpad_thread_state_data_t state) {
|
||||
ppc_thread_state64_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state64_t *>(state);
|
||||
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, srr0);
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContextPPC(breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location)
|
||||
{
|
||||
TypedMDRVA<MDRawContextPPC> context(&writer_);
|
||||
ppc_thread_state_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state_t *>(state);
|
||||
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
|
||||
*register_location = context.location();
|
||||
MinidumpContext *context_ptr = context.get();
|
||||
MDRawContextPPC *context_ptr = context.get();
|
||||
context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
|
||||
|
||||
#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
|
||||
|
|
@ -402,57 +470,124 @@ bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
|||
AddGPR(29);
|
||||
AddGPR(30);
|
||||
AddGPR(31);
|
||||
|
||||
#if TARGET_CPU_PPC
|
||||
/* The mq register is only for PPC */
|
||||
AddReg(mq);
|
||||
#endif
|
||||
|
||||
#undef AddReg
|
||||
#undef AddGPR
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif TARGET_CPU_X86 || TARGET_CPU_X86_64
|
||||
|
||||
bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
|
||||
#if TARGET_CPU_X86_64
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, rsp);
|
||||
#else
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp);
|
||||
#endif
|
||||
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) {
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
|
||||
#if TARGET_CPU_X86_64
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, rip);
|
||||
#else
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, eip);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MinidumpContext> context(&writer_);
|
||||
breakpad_thread_state_t *machine_state =
|
||||
reinterpret_cast<breakpad_thread_state_t *>(state);
|
||||
bool MinidumpGenerator::WriteContextPPC64(
|
||||
breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MDRawContextPPC64> context(&writer_);
|
||||
ppc_thread_state64_t *machine_state =
|
||||
reinterpret_cast<ppc_thread_state64_t *>(state);
|
||||
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
|
||||
*register_location = context.location();
|
||||
MinidumpContext *context_ptr = context.get();
|
||||
MDRawContextPPC64 *context_ptr = context.get();
|
||||
context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
|
||||
|
||||
#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
|
||||
#if TARGET_CPU_X86
|
||||
#define AddGPR(a) context_ptr->gpr[a] = REGISTER_FROM_THREADSTATE(machine_state, r ## a)
|
||||
|
||||
AddReg(srr0);
|
||||
AddReg(cr);
|
||||
AddReg(xer);
|
||||
AddReg(ctr);
|
||||
AddReg(lr);
|
||||
AddReg(vrsave);
|
||||
|
||||
AddGPR(0);
|
||||
AddGPR(1);
|
||||
AddGPR(2);
|
||||
AddGPR(3);
|
||||
AddGPR(4);
|
||||
AddGPR(5);
|
||||
AddGPR(6);
|
||||
AddGPR(7);
|
||||
AddGPR(8);
|
||||
AddGPR(9);
|
||||
AddGPR(10);
|
||||
AddGPR(11);
|
||||
AddGPR(12);
|
||||
AddGPR(13);
|
||||
AddGPR(14);
|
||||
AddGPR(15);
|
||||
AddGPR(16);
|
||||
AddGPR(17);
|
||||
AddGPR(18);
|
||||
AddGPR(19);
|
||||
AddGPR(20);
|
||||
AddGPR(21);
|
||||
AddGPR(22);
|
||||
AddGPR(23);
|
||||
AddGPR(24);
|
||||
AddGPR(25);
|
||||
AddGPR(26);
|
||||
AddGPR(27);
|
||||
AddGPR(28);
|
||||
AddGPR(29);
|
||||
AddGPR(30);
|
||||
AddGPR(31);
|
||||
#undef AddReg
|
||||
#undef AddGPR
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
i386_thread_state_t *machine_state =
|
||||
reinterpret_cast<i386_thread_state_t *>(state);
|
||||
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp);
|
||||
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state,
|
||||
MDMemoryDescriptor *stack_location) {
|
||||
x86_thread_state64_t *machine_state =
|
||||
reinterpret_cast<x86_thread_state64_t *>(state);
|
||||
|
||||
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, rsp);
|
||||
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
MinidumpGenerator::CurrentPCForStackX86(breakpad_thread_state_data_t state) {
|
||||
i386_thread_state_t *machine_state =
|
||||
reinterpret_cast<i386_thread_state_t *>(state);
|
||||
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, eip);
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
MinidumpGenerator::CurrentPCForStackX86_64(breakpad_thread_state_data_t state) {
|
||||
x86_thread_state64_t *machine_state =
|
||||
reinterpret_cast<x86_thread_state64_t *>(state);
|
||||
|
||||
return REGISTER_FROM_THREADSTATE(machine_state, rip);
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContextX86(breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location)
|
||||
{
|
||||
TypedMDRVA<MDRawContextX86> context(&writer_);
|
||||
i386_thread_state_t *machine_state =
|
||||
reinterpret_cast<i386_thread_state_t *>(state);
|
||||
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
|
||||
*register_location = context.location();
|
||||
MDRawContextX86 *context_ptr = context.get();
|
||||
|
||||
#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
|
||||
|
||||
context_ptr->context_flags = MD_CONTEXT_X86;
|
||||
AddReg(eax);
|
||||
AddReg(ebx);
|
||||
|
|
@ -472,7 +607,26 @@ bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
|||
AddReg(eflags);
|
||||
|
||||
AddReg(eip);
|
||||
#else
|
||||
#undef AddReg(a)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteContextX86_64(
|
||||
breakpad_thread_state_data_t state,
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MDRawContextAMD64> context(&writer_);
|
||||
x86_thread_state64_t *machine_state =
|
||||
reinterpret_cast<x86_thread_state64_t *>(state);
|
||||
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
|
||||
*register_location = context.location();
|
||||
MDRawContextAMD64 *context_ptr = context.get();
|
||||
|
||||
#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a)
|
||||
|
||||
context_ptr->context_flags = MD_CONTEXT_AMD64;
|
||||
AddReg(rax);
|
||||
AddReg(rbx);
|
||||
|
|
@ -495,16 +649,38 @@ bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
|||
// not used in the flags register. Since the minidump format
|
||||
// specifies 32 bits for the flags register, we can truncate safely
|
||||
// with no loss.
|
||||
context_ptr->eflags = static_cast<u_int32_t>(machine_state->__rflags);
|
||||
context_ptr->eflags = static_cast<u_int32_t>(REGISTER_FROM_THREADSTATE(machine_state, rflags));
|
||||
AddReg(cs);
|
||||
AddReg(fs);
|
||||
AddReg(gs);
|
||||
#endif
|
||||
#undef AddReg(a)
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||
thread_state_t state,
|
||||
mach_msg_type_number_t *count) {
|
||||
thread_state_flavor_t flavor;
|
||||
switch (cpu_type_) {
|
||||
case CPU_TYPE_POWERPC:
|
||||
flavor = PPC_THREAD_STATE;
|
||||
break;
|
||||
case CPU_TYPE_POWERPC64:
|
||||
flavor = PPC_THREAD_STATE64;
|
||||
break;
|
||||
case CPU_TYPE_I386:
|
||||
flavor = i386_THREAD_STATE;
|
||||
break;
|
||||
case CPU_TYPE_X86_64:
|
||||
flavor = x86_THREAD_STATE64;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return thread_get_state(target_thread, flavor,
|
||||
state, count) == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
||||
MDRawThread *thread) {
|
||||
|
|
@ -512,9 +688,7 @@ bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
|||
mach_msg_type_number_t state_count
|
||||
= static_cast<mach_msg_type_number_t>(sizeof(state));
|
||||
|
||||
if (thread_get_state(thread_id, BREAKPAD_MACHINE_THREAD_STATE,
|
||||
state, &state_count) ==
|
||||
KERN_SUCCESS) {
|
||||
if (GetThreadState(thread_id, state, &state_count)) {
|
||||
if (!WriteStack(state, &thread->stack))
|
||||
return false;
|
||||
|
||||
|
|
@ -653,21 +827,15 @@ bool MinidumpGenerator::WriteMemoryListStream(
|
|||
|
||||
if (dynamic_images_) {
|
||||
// Out-of-process.
|
||||
kern_return_t kr;
|
||||
|
||||
void *memory =
|
||||
ReadTaskMemory(
|
||||
crashing_task_,
|
||||
reinterpret_cast<const void *>(ip_memory_d.start_of_memory_range),
|
||||
ip_memory_d.memory.data_size,
|
||||
&kr);
|
||||
|
||||
if (memory == NULL) {
|
||||
vector<uint8_t> memory;
|
||||
if (ReadTaskMemory(crashing_task_,
|
||||
ip_memory_d.start_of_memory_range,
|
||||
ip_memory_d.memory.data_size,
|
||||
memory) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_memory.Copy(memory, ip_memory_d.memory.data_size);
|
||||
free(memory);
|
||||
ip_memory.Copy(&memory[0], ip_memory_d.memory.data_size);
|
||||
} else {
|
||||
// In-process, just copy from local memory.
|
||||
ip_memory.Copy(
|
||||
|
|
@ -733,23 +901,23 @@ bool MinidumpGenerator::WriteSystemInfoStream(
|
|||
system_info_stream->location = info.location();
|
||||
|
||||
// CPU Information
|
||||
uint32_t cpu_type;
|
||||
size_t len = sizeof(cpu_type);
|
||||
sysctlbyname("hw.cputype", &cpu_type, &len, NULL, 0);
|
||||
uint32_t number_of_processors;
|
||||
len = sizeof(number_of_processors);
|
||||
size_t len = sizeof(number_of_processors);
|
||||
sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0);
|
||||
MDRawSystemInfo *info_ptr = info.get();
|
||||
|
||||
switch (cpu_type) {
|
||||
switch (cpu_type_) {
|
||||
case CPU_TYPE_POWERPC:
|
||||
case CPU_TYPE_POWERPC64:
|
||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC;
|
||||
break;
|
||||
case CPU_TYPE_I386:
|
||||
case CPU_TYPE_X86_64:
|
||||
// hw.cputype is currently always I386 even on an x86-64 system
|
||||
if (cpu_type_ == CPU_TYPE_I386)
|
||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
|
||||
else
|
||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64;
|
||||
#ifdef __i386__
|
||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
|
||||
// ebx is used for PIC code, so we need
|
||||
// to preserve it.
|
||||
#define cpuid(op,eax,ebx,ecx,edx) \
|
||||
|
|
@ -763,7 +931,7 @@ bool MinidumpGenerator::WriteSystemInfoStream(
|
|||
"=d" (edx) \
|
||||
: "0" (op))
|
||||
#elif defined(__x86_64__)
|
||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64;
|
||||
|
||||
#define cpuid(op,eax,ebx,ecx,edx) \
|
||||
asm ("cpuid \n\t" \
|
||||
: "=a" (eax), \
|
||||
|
|
@ -837,19 +1005,12 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||
if (!image)
|
||||
return false;
|
||||
|
||||
const breakpad_mach_header *header = image->GetMachHeader();
|
||||
|
||||
if (!header)
|
||||
return false;
|
||||
|
||||
int cpu_type = header->cputype;
|
||||
|
||||
memset(module, 0, sizeof(MDRawModule));
|
||||
|
||||
MDLocationDescriptor string_location;
|
||||
|
||||
const char* name = image->GetFilePath();
|
||||
if (!writer_.WriteString(name, 0, &string_location))
|
||||
string name = image->GetFilePath();
|
||||
if (!writer_.WriteString(name.c_str(), 0, &string_location))
|
||||
return false;
|
||||
|
||||
module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide();
|
||||
|
|
@ -876,12 +1037,11 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||
module->version_info.file_version_lo |= (modVersion & 0xff);
|
||||
}
|
||||
|
||||
if (!WriteCVRecord(module, cpu_type, name)) {
|
||||
if (!WriteCVRecord(module, image->GetCPUType(), name.c_str())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// we're getting module info in the crashed process
|
||||
|
||||
// Getting module info in the crashed process
|
||||
const breakpad_mach_header *header;
|
||||
header = (breakpad_mach_header*)_dyld_get_image_header(index);
|
||||
if (!header)
|
||||
|
|
@ -903,7 +1063,7 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||
unsigned long slide = _dyld_get_image_vmaddr_slide(index);
|
||||
const char* name = _dyld_get_image_name(index);
|
||||
const struct load_command *cmd =
|
||||
reinterpret_cast<const struct load_command *>(header + 1);
|
||||
reinterpret_cast<const struct load_command *>(header + 1);
|
||||
|
||||
memset(module, 0, sizeof(MDRawModule));
|
||||
|
||||
|
|
@ -911,7 +1071,7 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||
if (cmd->cmd == LC_SEGMENT_ARCH) {
|
||||
|
||||
const breakpad_mach_segment_command *seg =
|
||||
reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
|
||||
reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
|
||||
|
||||
if (!strcmp(seg->segname, "__TEXT")) {
|
||||
MDLocationDescriptor string_location;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue