aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/mac/handler/minidump_generator.cc56
-rw-r--r--src/client/mac/handler/minidump_generator.h3
2 files changed, 32 insertions, 27 deletions
diff --git a/src/client/mac/handler/minidump_generator.cc b/src/client/mac/handler/minidump_generator.cc
index 4f388e6f..a7680c21 100644
--- a/src/client/mac/handler/minidump_generator.cc
+++ b/src/client/mac/handler/minidump_generator.cc
@@ -255,37 +255,45 @@ size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) {
kern_return_t result =
mach_vm_region_recurse(crashing_task_, &stack_region_base,
&stack_region_size, &nesting_level,
- region_info,
- &info_count);
+ region_info, &info_count);
- if (start_addr < stack_region_base) {
- // probably stack corruption, since mach_vm_region had to go
+ if (result != KERN_SUCCESS || start_addr < stack_region_base) {
+ // Failure or stack corruption, since mach_vm_region had to go
// higher in the process address space to find a valid region.
return 0;
}
- 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
- // below this, and is then later extended to a much larger size by
- // creating a new VM region immediately below the initial page.
-
- // You can see this for yourself by running vmmap on a "hello,
- // world" program
-
- // Because of the above, we'll add 4k to include the original
- // stack frame page.
- // This method of finding the stack region needs to be done in
- // a better way; the breakpad issue 247 is tracking this.
- stack_region_size += 0x1000;
+ unsigned int tag = submap_info.user_tag;
+
+ // If the user tag is VM_MEMORY_STACK, look for more readable regions with
+ // the same tag placed immediately above the computed stack region. Under
+ // some circumstances, the stack for thread 0 winds up broken up into
+ // multiple distinct abutting regions. This can happen for several reasons,
+ // including user code that calls setrlimit(RLIMIT_STACK, ...) or changes
+ // the access on stack pages by calling mprotect.
+ if (tag == VM_MEMORY_STACK) {
+ while (true) {
+ mach_vm_address_t next_region_base = stack_region_base +
+ stack_region_size;
+ mach_vm_address_t proposed_next_region_base = next_region_base;
+ mach_vm_size_t next_region_size;
+ nesting_level = 0;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ result = mach_vm_region_recurse(crashing_task_, &next_region_base,
+ &next_region_size, &nesting_level,
+ region_info, &info_count);
+ if (result != KERN_SUCCESS ||
+ next_region_base != proposed_next_region_base ||
+ submap_info.user_tag != tag ||
+ submap_info.protection & VM_PROT_READ == 0) {
+ break;
+ }
+
+ stack_region_size += next_region_size;
+ }
}
- return result == KERN_SUCCESS ?
- stack_region_base + stack_region_size - start_addr : 0;
+ return stack_region_base + stack_region_size - start_addr;
}
bool MinidumpGenerator::WriteStackFromStartAddress(
diff --git a/src/client/mac/handler/minidump_generator.h b/src/client/mac/handler/minidump_generator.h
index 55c4c8a3..6f9fe8f7 100644
--- a/src/client/mac/handler/minidump_generator.h
+++ b/src/client/mac/handler/minidump_generator.h
@@ -51,9 +51,6 @@ namespace google_breakpad {
using std::string;
-const u_int64_t TOP_OF_THREAD0_STACK_64BIT = 0x00007fff5fbff000LL;
-const u_int32_t TOP_OF_THREAD0_STACK_32BIT = 0xbffff000;
-
// Use the REGISTER_FROM_THREADSTATE to access a register name from the
// breakpad_thread_state_t structure.
#if __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64