| OLD | NEW |
| 1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 #endif | 58 #endif |
| 59 #ifdef HAVE_UNISTD_H | 59 #ifdef HAVE_UNISTD_H |
| 60 #include <unistd.h> | 60 #include <unistd.h> |
| 61 #endif | 61 #endif |
| 62 #ifdef HAVE_MMAP | 62 #ifdef HAVE_MMAP |
| 63 #include <sys/mman.h> // for msync | 63 #include <sys/mman.h> // for msync |
| 64 #include "base/vdso_support.h" | 64 #include "base/vdso_support.h" |
| 65 #endif | 65 #endif |
| 66 | 66 |
| 67 #include "google/stacktrace.h" | 67 #include "google/stacktrace.h" |
| 68 #if defined(KEEP_SHADOW_STACKS) | |
| 69 #include "linux_shadow_stacks.h" | |
| 70 #endif // KEEP_SHADOW_STACKS | |
| 71 | 68 |
| 72 #if defined(__linux__) && defined(__i386__) && defined(__ELF__) && defined(HAVE_
MMAP) | 69 #if defined(__linux__) && defined(__i386__) && defined(__ELF__) && defined(HAVE_
MMAP) |
| 73 // Count "push %reg" instructions in VDSO __kernel_vsyscall(), | 70 // Count "push %reg" instructions in VDSO __kernel_vsyscall(), |
| 74 // preceeding "syscall" or "sysenter". | 71 // preceeding "syscall" or "sysenter". |
| 75 // If __kernel_vsyscall uses frame pointer, answer 0. | 72 // If __kernel_vsyscall uses frame pointer, answer 0. |
| 76 // | 73 // |
| 77 // kMaxBytes tells how many instruction bytes of __kernel_vsyscall | 74 // kMaxBytes tells how many instruction bytes of __kernel_vsyscall |
| 78 // to analyze before giving up. Up to kMaxBytes+1 bytes of | 75 // to analyze before giving up. Up to kMaxBytes+1 bytes of |
| 79 // instructions could be accessed. | 76 // instructions could be accessed. |
| 80 // | 77 // |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 if (STRICT_UNWINDING) { | 231 if (STRICT_UNWINDING) { |
| 235 // With the stack growing downwards, older stack frame must be | 232 // With the stack growing downwards, older stack frame must be |
| 236 // at a greater address that the current one. | 233 // at a greater address that the current one. |
| 237 if (new_sp <= old_sp) return NULL; | 234 if (new_sp <= old_sp) return NULL; |
| 238 // Assume stack frames larger than 100,000 bytes are bogus. | 235 // Assume stack frames larger than 100,000 bytes are bogus. |
| 239 if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; | 236 if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; |
| 240 } else { | 237 } else { |
| 241 // In the non-strict mode, allow discontiguous stack frames. | 238 // In the non-strict mode, allow discontiguous stack frames. |
| 242 // (alternate-signal-stacks for example). | 239 // (alternate-signal-stacks for example). |
| 243 if (new_sp == old_sp) return NULL; | 240 if (new_sp == old_sp) return NULL; |
| 244 // And allow frames upto about 1MB. | 241 if (new_sp > old_sp) { |
| 245 if ((new_sp > old_sp) | 242 // And allow frames upto about 1MB. |
| 246 && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL; | 243 const uintptr_t delta = (uintptr_t)new_sp - (uintptr_t)old_sp; |
| 244 const uintptr_t acceptable_delta = 1000000; |
| 245 if (delta > acceptable_delta) { |
| 246 return NULL; |
| 247 } |
| 248 } |
| 247 } | 249 } |
| 248 if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; | 250 if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; |
| 249 #ifdef __i386__ | 251 #ifdef __i386__ |
| 250 // On 64-bit machines, the stack pointer can be very close to | 252 // On 64-bit machines, the stack pointer can be very close to |
| 251 // 0xffffffff, so we explicitly check for a pointer into the | 253 // 0xffffffff, so we explicitly check for a pointer into the |
| 252 // last two pages in the address space | 254 // last two pages in the address space |
| 253 if ((uintptr_t)new_sp >= 0xffffe000) return NULL; | 255 if ((uintptr_t)new_sp >= 0xffffe000) return NULL; |
| 254 #endif | 256 #endif |
| 255 #ifdef HAVE_MMAP | 257 #ifdef HAVE_MMAP |
| 256 if (!STRICT_UNWINDING) { | 258 if (!STRICT_UNWINDING) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // static void Noop() { asm(""); } // prevent optimizing-away | 314 // static void Noop() { asm(""); } // prevent optimizing-away |
| 313 __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp)); | 315 __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp)); |
| 314 // Arguments are passed in registers on x86-64, so we can't just | 316 // Arguments are passed in registers on x86-64, so we can't just |
| 315 // offset from &result | 317 // offset from &result |
| 316 sp = (void **) rbp; | 318 sp = (void **) rbp; |
| 317 #else | 319 #else |
| 318 # error Using stacktrace_x86-inl.h on a non x86 architecture! | 320 # error Using stacktrace_x86-inl.h on a non x86 architecture! |
| 319 #endif | 321 #endif |
| 320 | 322 |
| 321 int n = 0; | 323 int n = 0; |
| 322 #if defined(KEEP_SHADOW_STACKS) | |
| 323 void **shadow_ip_stack; | |
| 324 void **shadow_sp_stack; | |
| 325 int stack_size; | |
| 326 shadow_ip_stack = (void**) get_shadow_ip_stack(&stack_size); | |
| 327 shadow_sp_stack = (void**) get_shadow_sp_stack(&stack_size); | |
| 328 int shadow_index = stack_size - 1; | |
| 329 for (int i = stack_size - 1; i >= 0; i--) { | |
| 330 if (sp == shadow_sp_stack[i]) { | |
| 331 shadow_index = i; | |
| 332 break; | |
| 333 } | |
| 334 } | |
| 335 void **prev_sp = NULL; | |
| 336 #endif // KEEP_SHADOW_STACKS | |
| 337 while (sp && n < max_depth) { | 324 while (sp && n < max_depth) { |
| 338 if (*(sp+1) == reinterpret_cast<void *>(0)) { | 325 if (*(sp+1) == reinterpret_cast<void *>(0)) { |
| 339 // In 64-bit code, we often see a frame that | 326 // In 64-bit code, we often see a frame that |
| 340 // points to itself and has a return address of 0. | 327 // points to itself and has a return address of 0. |
| 341 break; | 328 break; |
| 342 } | 329 } |
| 343 #if !IS_WITH_CONTEXT | 330 #if !IS_WITH_CONTEXT |
| 344 const void *const ucp = NULL; | 331 const void *const ucp = NULL; |
| 345 #endif | 332 #endif |
| 346 void **next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp); | 333 void **next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp); |
| 347 if (skip_count > 0) { | 334 if (skip_count > 0) { |
| 348 skip_count--; | 335 skip_count--; |
| 349 #if defined(KEEP_SHADOW_STACKS) | |
| 350 shadow_index--; | |
| 351 #endif // KEEP_SHADOW_STACKS | |
| 352 } else { | 336 } else { |
| 353 result[n] = *(sp+1); | 337 result[n] = *(sp+1); |
| 354 #if defined(KEEP_SHADOW_STACKS) | |
| 355 if ((shadow_index > 0) && (sp == shadow_sp_stack[shadow_index])) { | |
| 356 shadow_index--; | |
| 357 } | |
| 358 #endif // KEEP_SHADOW_STACKS | |
| 359 | |
| 360 #if IS_STACK_FRAMES | 338 #if IS_STACK_FRAMES |
| 361 if (next_sp > sp) { | 339 if (next_sp > sp) { |
| 362 sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; | 340 sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; |
| 363 } else { | 341 } else { |
| 364 // A frame-size of 0 is used to indicate unknown frame size. | 342 // A frame-size of 0 is used to indicate unknown frame size. |
| 365 sizes[n] = 0; | 343 sizes[n] = 0; |
| 366 } | 344 } |
| 367 #endif | 345 #endif |
| 368 n++; | 346 n++; |
| 369 } | 347 } |
| 370 #if defined(KEEP_SHADOW_STACKS) | |
| 371 prev_sp = sp; | |
| 372 #endif // KEEP_SHADOW_STACKS | |
| 373 sp = next_sp; | 348 sp = next_sp; |
| 374 } | 349 } |
| 375 | |
| 376 #if defined(KEEP_SHADOW_STACKS) | |
| 377 if (shadow_index >= 0) { | |
| 378 for (int i = shadow_index; i >= 0; i--) { | |
| 379 if (shadow_sp_stack[i] > prev_sp) { | |
| 380 result[n] = shadow_ip_stack[i]; | |
| 381 if (n + 1 < max_depth) { | |
| 382 n++; | |
| 383 continue; | |
| 384 } | |
| 385 } | |
| 386 break; | |
| 387 } | |
| 388 } | |
| 389 #endif // KEEP_SHADOW_STACKS | |
| 390 return n; | 350 return n; |
| 391 } | 351 } |
| OLD | NEW |