• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "partition_alloc/partition_alloc_base/debug/stack_trace.h"
6 
7 #include "partition_alloc/partition_alloc_base/logging.h"
8 #include "partition_alloc/partition_alloc_base/strings/safe_sprintf.h"
9 
10 #include <string.h>
11 #include <unistd.h>
12 #include <unwind.h>
13 
14 namespace partition_alloc::internal::base::debug {
15 
16 namespace {
17 
18 struct StackCrawlState {
StackCrawlStatepartition_alloc::internal::base::debug::__anonad7a07070111::StackCrawlState19   StackCrawlState(uintptr_t* frames, size_t max_depth)
20       : frames(frames),
21         frame_count(0),
22         max_depth(max_depth),
23         have_skipped_self(false) {}
24 
25   uintptr_t* frames;
26   size_t frame_count;
27   size_t max_depth;
28   bool have_skipped_self;
29 };
30 
TraceStackFrame(_Unwind_Context * context,void * arg)31 _Unwind_Reason_Code TraceStackFrame(_Unwind_Context* context, void* arg) {
32   StackCrawlState* state = static_cast<StackCrawlState*>(arg);
33   uintptr_t ip = _Unwind_GetIP(context);
34 
35   // The first stack frame is this function itself.  Skip it.
36   if (ip != 0 && !state->have_skipped_self) {
37     state->have_skipped_self = true;
38     return _URC_NO_REASON;
39   }
40 
41   state->frames[state->frame_count++] = ip;
42   if (state->frame_count >= state->max_depth) {
43     return _URC_END_OF_STACK;
44   }
45   return _URC_NO_REASON;
46 }
47 
48 }  // namespace
49 
CollectStackTrace(const void ** trace,size_t count)50 size_t CollectStackTrace(const void** trace, size_t count) {
51   StackCrawlState state(reinterpret_cast<uintptr_t*>(trace), count);
52   _Unwind_Backtrace(&TraceStackFrame, &state);
53   return state.frame_count;
54 }
55 
OutputStackTrace(unsigned index,uintptr_t address,uintptr_t base_address,const char * module_name,uintptr_t offset)56 void OutputStackTrace(unsigned index,
57                       uintptr_t address,
58                       uintptr_t base_address,
59                       const char* module_name,
60                       uintptr_t offset) {
61   size_t module_name_len = strlen(module_name);
62 
63   char buffer[256];
64   if (module_name_len > 4 &&
65       !strcmp(module_name + module_name_len - 4, ".apk")) {
66     strings::SafeSPrintf(buffer, "#%02d pc 0x%0x %s (offset 0x%0x)\n", index,
67                          address - base_address, module_name, offset);
68   } else {
69     strings::SafeSPrintf(buffer, "#%02d pc 0x%0x %s\n", index,
70                          address - base_address, module_name);
71   }
72   PA_RAW_LOG(INFO, buffer);
73 }
74 
75 }  // namespace partition_alloc::internal::base::debug
76