1 /**************************************************************************
3 * Copyright 2013 Samsung
4 * Contributed by Eugene Velesevich
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
28 * Wrapper for platform-specific code for obtaining symbolic backtraces
29 * on Android and Linux
34 #include "trace_backtrace.hpp"
36 #if defined(ANDROID) or defined(__linux__)
45 * Pascal string (with zero terminator optionally omitted)
46 * This is a helper class for storing a set of exact strings or prefixes
47 * to match a zero-terminated string against later.
48 * Two zero-terminated pstrings compare equal iff they are the same.
49 * Otherwise, they compare equal iff one is a prefix of the other
50 * (a zero-terminated pstring cannot be a prefix)
56 pstring(const char* s, int n)
61 bool operator<(const pstring q2) const
63 return memcmp(s, q2.s, n < q2.n? n : q2.n) < 0;
68 #define PREFIX_BUF_SIZE (PREFIX_MAX_FUNC_NAME * MAX_BT_FUNC)
70 class StringPrefixes {
72 std::set<pstring> pset;
75 void addPrefix(char* startbuf, int n) {
76 std::set<pstring>::iterator elem = pset.find(pstring(startbuf, n));
77 bool replace = elem != pset.end() && n < elem->n;
81 if (replace || elem == pset.end()) {
82 pset.insert(pstring(startbuf, n));
86 StringPrefixes(const char* source);
88 bool contain(const char* s) {
89 if (pset.find(pstring(s, strlen(s) + 1)) != pset.end()) {
90 os::log("Backtrace for %s is enabled", s);
97 bool backtrace_is_needed(const char* fname) {
98 static StringPrefixes backtraceFunctionNamePrefixes(APITRACE_FNAMES_SOURCE);
99 return backtraceFunctionNamePrefixes.contain(fname);
102 } /* namespace trace */
112 StringPrefixes::StringPrefixes(const char* source) {
113 buf = (char*)malloc(sizeof(char) * PREFIX_BUF_SIZE);
114 char* startbuf = buf;
116 FILE* f = fopen(source, "r");
118 os::log("Cannot open " APITRACE_FNAMES_FILE);
120 while ((startbuf = fgets(startbuf, PREFIX_MAX_FUNC_NAME, f))) {
121 n = strlen(startbuf);
122 if (startbuf[n - 1] == '\n') {
125 if (n > 2 && startbuf[0] != '#') {
127 if (startbuf[n - 1] != '*') {
134 addPrefix(startbuf, psize);
143 /* The following two declarations are copied from Android sources */
145 enum DebugTargetKind {
146 kDebugTargetUnknown = 0,
151 struct DebugOutputTarget {
152 DebugTargetKind which;
165 #define THREAD_SELF_NAME "_Z13dvmThreadSelfv"
166 #define CREATE_DEBUG_TARGET_NAME "_Z25dvmCreateFileOutputTargetP17DebugOutputTargetP7__sFILE"
167 #define DUMP_BACKTRACE_NAME "_Z18dvmDumpThreadStackPK17DebugOutputTargetP6Thread"
170 class DalvikBacktraceProvider {
173 void* (*threadself)(void);
174 FILE* streamInMemory;
177 void (*dumpBacktrace)(const DebugOutputTarget*, void*);
178 DebugOutputTarget debugTarget;
181 DalvikBacktraceProvider() {
183 FILE* (*open_memstream_exp)(char**, size_t*);
184 void (*createDebugTarget)(DebugOutputTarget*, FILE*);
185 void* handle = dlopen("/system/lib/libdvm.so", 0);
188 os::log("dlopen failed\n");
191 threadself = (void* (*)())dlsym(handle, THREAD_SELF_NAME);
192 if (threadself == NULL) {
193 os::log("dlsym ThreadSelf failed\n");
196 createDebugTarget = (void (*)(DebugOutputTarget*, FILE*))dlsym(handle, CREATE_DEBUG_TARGET_NAME);
197 if (createDebugTarget == NULL) {
198 os::log("dlsym CreateFileOutput failed\n");
201 dumpBacktrace = (void (*)(const DebugOutputTarget*, void*))dlsym(handle, DUMP_BACKTRACE_NAME);
202 if (dumpBacktrace == NULL) {
203 os::log("dlsym DumpThreadStack failed\n");
206 void* handle2 = dlopen("/system/lib/libcutils.so", 0);
208 os::log("dlopen failed\n");
211 open_memstream_exp = (FILE* (*)(char**, size_t*))dlsym(handle2, "open_memstream");
212 if (open_memstream_exp == NULL) {
213 os::log("dlsym open_memstream failed\n");
216 streamInMemory = open_memstream_exp(&buf, &bufSize);
217 if (streamInMemory == NULL) {
218 os::log("open_memstream failed\n");
221 createDebugTarget(&debugTarget, streamInMemory);
222 errorOccured = false;
225 inline char* getBacktrace() {
229 rewind(streamInMemory);
230 dumpBacktrace(&debugTarget, threadself());
231 fflush(streamInMemory);
235 * Parse a stack frame, expecting:
236 * " at android.view.HardwareRenderer$GlRenderer.initializeEgl(HardwareRenderer.java:547)"
238 * " at android.view.HardwareRenderer$GlRenderer.initializeEgl(Native Method)"
240 std::vector<RawStackFrame> parseBacktrace(char *rawBacktrace) {
241 std::vector<RawStackFrame> parsedBacktrace;
242 char* rawBacktrace_it = rawBacktrace;
243 while (*rawBacktrace_it != '\0') {
244 RawStackFrame stackFrame;
245 // TODO: Keep a cache of stack frames
246 stackFrame->id = nextFrameId++;
247 /* skip leading space */
248 while (*rawBacktrace_it == ' ') {
252 rawBacktrace_it += 3;
253 stackFrame.function = rawBacktrace_it;
254 while (*rawBacktrace_it != '(') {
257 *rawBacktrace_it = '\0';
258 stackFrame.filename = rawBacktrace_it + 1;
259 while (*rawBacktrace_it != ':' && *rawBacktrace_it != ')') {
262 if (*rawBacktrace_it == ':') {
263 const char *linenumber = rawBacktrace_it + 1;
264 *rawBacktrace_it = '\0';
265 while (*rawBacktrace_it != ')') {
268 *rawBacktrace_it = '\0';
270 stackFrame.linenumber = atoi(linenumber);
273 stackFrame.filename = NULL;
274 while (*rawBacktrace_it != '\n') {
278 while (*rawBacktrace_it == '\n' || *rawBacktrace_it == ' ') {
281 parsedBacktrace.push_back(stackFrame); /* module */
283 return parsedBacktrace;
287 std::vector<RawStackFrame> get_backtrace() {
288 static DalvikBacktraceProvider backtraceProvider;
289 return backtraceProvider.parseBacktrace(backtraceProvider.getBacktrace());
293 #elif defined __linux__
295 #include <execinfo.h>
305 StringPrefixes::StringPrefixes(const char* source) {
306 buf = (char*)malloc(sizeof(char) * PREFIX_BUF_SIZE);
307 char* startbuf = buf;
309 char* s = getenv(source);
315 strncpy(buf + 1, s, PREFIX_BUF_SIZE - 2);
316 while (end != '\0') {
318 while (*(startbuf + n) != ';' && *(startbuf + n) != '\0') {
322 if (n > 2 && startbuf[0] != '#') {
324 if (startbuf[n - 1] != '*') {
331 addPrefix(startbuf, psize);
341 class GlibcBacktraceProvider {
343 std::map<void*, RawStackFrame*> cache;
345 * Backtrace being returned by glibc backtrace() contains stack frames
346 * belonging to apitrace wrapper module. We count the number of apitrace
347 * functions on the stack to avoid recording these frames.
349 int numOfNestedFunctions;
353 * Parse a stack frame, expecting:
354 * /lib/libc.so.6.1(__libc_start_main+0x50308) [0x2000000000097630]
356 * /lib/libc.so.6.1(+0x50308) [0x2000000000097630]
358 * /lib/libc.so.6.1() [0x2000000000097630]
360 RawStackFrame* parseFrame(void* frame, char* frame_symbol) {
361 if (cache.find(frame) == cache.end()) {
362 char* frame_symbol_copy = new char[strlen(frame_symbol) + 1];
363 strcpy(frame_symbol_copy, frame_symbol);
364 RawStackFrame* parsedFrame = new RawStackFrame;
365 parsedFrame->id = nextFrameId++;
366 char* frame_it = frame_symbol_copy;
367 parsedFrame->module = frame_it;
374 if (*frame_it != ')' && *frame_it != '+') {
375 parsedFrame->function = frame_it;
376 while (*frame_it != '+' && *frame_it != ')') {
390 sscanf(offset, "%llx", &parsedFrame->offset);
391 cache[frame] = parsedFrame;
395 delete[] frame_symbol_copy;
396 delete[] parsedFrame;
408 GlibcBacktraceProvider() :
409 numOfNestedFunctions(0),
413 std::vector<RawStackFrame> getParsedBacktrace() {
414 std::vector<RawStackFrame> parsedBacktrace;
415 void *array[numOfNestedFunctions + BT_DEPTH];
419 const char* firstModule;
420 size = backtrace(array, numOfNestedFunctions + BT_DEPTH);
421 strings = backtrace_symbols(array, size);
422 for (i = numOfNestedFunctions; i < size; i++) {
423 RawStackFrame* parsedFrame = parseFrame(array[i], strings[i]);
424 if (numOfNestedFunctions == 0) {
426 firstModule = parsedFrame->module;
429 if (strcmp(firstModule, parsedFrame->module)) {
430 numOfNestedFunctions = i;
432 parsedBacktrace = getParsedBacktrace();
433 numOfNestedFunctions--;
434 return parsedBacktrace;
438 if (parsedFrame != NULL) {
439 parsedBacktrace.push_back(*parsedFrame);
444 return parsedBacktrace;
449 std::vector<RawStackFrame> get_backtrace() {
450 static GlibcBacktraceProvider backtraceProvider;
451 return backtraceProvider.getParsedBacktrace();
456 } /* namespace trace */
458 #endif /* ANDROID or LINUX */