proxygen
StackTrace.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 
18 // Must be first to ensure that UNW_LOCAL_ONLY is defined
19 #define UNW_LOCAL_ONLY 1
20 #include <libunwind.h>
21 
22 namespace folly {
23 namespace symbolizer {
24 
25 ssize_t getStackTrace(uintptr_t* addresses, size_t maxAddresses) {
26  static_assert(
27  sizeof(uintptr_t) == sizeof(void*), "uintptr_t / pointer size mismatch");
28  // The libunwind documentation says that unw_backtrace is async-signal-safe
29  // but, as of libunwind 1.0.1, it isn't (tdep_trace allocates memory on
30  // x86_64)
31  int r = unw_backtrace(reinterpret_cast<void**>(addresses), maxAddresses);
32  return r < 0 ? -1 : r;
33 }
34 
35 namespace {
36 inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) {
37  unw_word_t uip;
38  if (unw_get_reg(cursor, UNW_REG_IP, &uip) < 0) {
39  return false;
40  }
41  int r = unw_is_signal_frame(cursor);
42  if (r < 0) {
43  return false;
44  }
45  // Use previous instruction in normal (call) frames (because the
46  // return address might not be in the same function for noreturn functions)
47  // but not in signal frames.
48  ip = uip - (r == 0);
49  return true;
50 }
51 } // namespace
52 
53 ssize_t getStackTraceSafe(uintptr_t* addresses, size_t maxAddresses) {
54  if (maxAddresses == 0) {
55  return 0;
56  }
57  unw_context_t context;
58  if (unw_getcontext(&context) < 0) {
59  return -1;
60  }
61  unw_cursor_t cursor;
62  if (unw_init_local(&cursor, &context) < 0) {
63  return -1;
64  }
65  if (!getFrameInfo(&cursor, *addresses)) {
66  return -1;
67  }
68  ++addresses;
69  size_t count = 1;
70  for (; count != maxAddresses; ++count, ++addresses) {
71  int r = unw_step(&cursor);
72  if (r < 0) {
73  return -1;
74  }
75  if (r == 0) {
76  break;
77  }
78  if (!getFrameInfo(&cursor, *addresses)) {
79  return -1;
80  }
81  }
82  return count;
83 }
84 } // namespace symbolizer
85 } // namespace folly
ssize_t getStackTraceSafe(uintptr_t *addresses, size_t maxAddresses)
Definition: StackTrace.cpp:53
context
Definition: CMakeCache.txt:563
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
ssize_t getStackTrace(uintptr_t *addresses, size_t maxAddresses)
Definition: StackTrace.cpp:25
int * count