1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <dlfcn.h>
30 #include <execinfo.h>
31 #include <inttypes.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/mman.h>
36 #include <unistd.h>
37 #include <unwind.h>
38
39 #include "private/ScopedFd.h"
40
41 struct StackState {
42 void** frames;
43 int frame_count;
44 int cur_frame = 0;
45
StackStateStackState46 StackState(void** frames, int frame_count) : frames(frames), frame_count(frame_count) {}
47 };
48
TraceFunction(_Unwind_Context * context,void * arg)49 static _Unwind_Reason_Code TraceFunction(_Unwind_Context* context, void* arg) {
50 // The instruction pointer is pointing at the instruction after the return
51 // call on all architectures.
52 // Modify the pc to point at the real function.
53 uintptr_t ip = _Unwind_GetIP(context);
54 if (ip != 0) {
55 #if defined(__arm__)
56 // If the ip is suspiciously low, do nothing to avoid a segfault trying
57 // to access this memory.
58 if (ip >= 4096) {
59 // Check bits [15:11] of the first halfword assuming the instruction
60 // is 32 bits long. If the bits are any of these values, then our
61 // assumption was correct:
62 // b11101
63 // b11110
64 // b11111
65 // Otherwise, this is a 16 bit instruction.
66 uint16_t value = (*reinterpret_cast<uint16_t*>(ip - 2)) >> 11;
67 if (value == 0x1f || value == 0x1e || value == 0x1d) {
68 ip -= 4;
69 } else {
70 ip -= 2;
71 }
72 }
73 #elif defined(__aarch64__)
74 // All instructions are 4 bytes long, skip back one instruction.
75 ip -= 4;
76 #elif defined(__riscv)
77 // C instructions are the shortest at 2 bytes long. (Unlike thumb, it's
78 // non-trivial to recognize C instructions when going backwards in the
79 // instruction stream.)
80 ip -= 2;
81 #elif defined(__i386__) || defined(__x86_64__)
82 // It's difficult to decode exactly where the previous instruction is,
83 // so subtract 1 to estimate where the instruction lives.
84 ip--;
85 #endif
86 }
87
88 StackState* state = static_cast<StackState*>(arg);
89 state->frames[state->cur_frame++] = reinterpret_cast<void*>(ip);
90 return (state->cur_frame >= state->frame_count) ? _URC_END_OF_STACK : _URC_NO_REASON;
91 }
92
backtrace(void ** buffer,int size)93 int backtrace(void** buffer, int size) {
94 if (size <= 0) {
95 return 0;
96 }
97
98 StackState state(buffer, size);
99 _Unwind_Backtrace(TraceFunction, &state);
100 return state.cur_frame;
101 }
102
backtrace_symbols(void * const * buffer,int size)103 char** backtrace_symbols(void* const* buffer, int size) {
104 if (size <= 0) {
105 return nullptr;
106 }
107 // Do this calculation first in case the user passes in a bad value.
108 size_t ptr_size;
109 if (__builtin_mul_overflow(sizeof(char*), size, &ptr_size)) {
110 return nullptr;
111 }
112
113 ScopedFd fd(memfd_create("backtrace_symbols_fd", MFD_CLOEXEC));
114 if (fd.get() == -1) {
115 return nullptr;
116 }
117 backtrace_symbols_fd(buffer, size, fd.get());
118
119 // Get the size of the file.
120 off_t file_size = lseek(fd.get(), 0, SEEK_END);
121 if (file_size <= 0) {
122 return nullptr;
123 }
124
125 // The interface for backtrace_symbols indicates that only the single
126 // returned pointer must be freed by the caller. Therefore, allocate a
127 // buffer that includes the memory for the strings and all of the pointers.
128 // Add one byte at the end just in case the file didn't end with a '\n'.
129 size_t symbol_data_size;
130 if (__builtin_add_overflow(ptr_size, file_size, &symbol_data_size) ||
131 __builtin_add_overflow(symbol_data_size, 1, &symbol_data_size)) {
132 return nullptr;
133 }
134
135 uint8_t* symbol_data = reinterpret_cast<uint8_t*>(malloc(symbol_data_size));
136 if (symbol_data == nullptr) {
137 return nullptr;
138 }
139
140 // Copy the string data into the buffer.
141 char* cur_string = reinterpret_cast<char*>(&symbol_data[ptr_size]);
142 // If this fails, the read won't read back the correct number of bytes.
143 lseek(fd.get(), 0, SEEK_SET);
144 ssize_t num_read = read(fd.get(), cur_string, file_size);
145 fd.reset(-1);
146 if (num_read != file_size) {
147 free(symbol_data);
148 return nullptr;
149 }
150
151 // Make sure the last character in the file is '\n'.
152 if (cur_string[file_size] != '\n') {
153 cur_string[file_size++] = '\n';
154 }
155
156 for (int i = 0; i < size; i++) {
157 (reinterpret_cast<char**>(symbol_data))[i] = cur_string;
158 cur_string = strchr(cur_string, '\n');
159 if (cur_string == nullptr) {
160 free(symbol_data);
161 return nullptr;
162 }
163 cur_string[0] = '\0';
164 cur_string++;
165 }
166 return reinterpret_cast<char**>(symbol_data);
167 }
168
169 // This function should do no allocations if possible.
backtrace_symbols_fd(void * const * buffer,int size,int fd)170 void backtrace_symbols_fd(void* const* buffer, int size, int fd) {
171 if (size <= 0 || fd < 0) {
172 return;
173 }
174
175 for (int frame_num = 0; frame_num < size; frame_num++) {
176 void* address = buffer[frame_num];
177 Dl_info info;
178 if (dladdr(address, &info) != 0) {
179 if (info.dli_fname != nullptr) {
180 write(fd, info.dli_fname, strlen(info.dli_fname));
181 }
182 if (info.dli_sname != nullptr) {
183 dprintf(fd, "(%s+0x%" PRIxPTR ") ", info.dli_sname,
184 reinterpret_cast<uintptr_t>(address) - reinterpret_cast<uintptr_t>(info.dli_saddr));
185 } else {
186 dprintf(fd, "(+%p) ", info.dli_saddr);
187 }
188 }
189
190 dprintf(fd, "[%p]\n", address);
191 }
192 }
193