blob: 2fed99333ba35af435a94f3d14433da95138b5b6 [file] [log] [blame]
Christopher Ferris17e91d42013-10-21 13:30:52 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
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 */
16
17#include <dirent.h>
18#include <errno.h>
19#include <pthread.h>
20#include <signal.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/ptrace.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <time.h>
29#include <unistd.h>
30
Christopher Ferris20303f82014-01-10 16:33:16 -080031#include <backtrace/Backtrace.h>
32#include <UniquePtr.h>
Christopher Ferris17e91d42013-10-21 13:30:52 -070033
34#include <cutils/atomic.h>
35#include <gtest/gtest.h>
36
37#include <vector>
38
39#include "thread_utils.h"
40
41// Number of microseconds per milliseconds.
42#define US_PER_MSEC 1000
43
44// Number of nanoseconds in a second.
45#define NS_PER_SEC 1000000000ULL
46
47// Number of simultaneous dumping operations to perform.
48#define NUM_THREADS 20
49
50// Number of simultaneous threads running in our forked process.
51#define NUM_PTRACE_THREADS 5
52
53typedef struct {
54 pid_t tid;
55 int32_t state;
56 pthread_t threadId;
57} thread_t;
58
59typedef struct {
60 thread_t thread;
Christopher Ferris20303f82014-01-10 16:33:16 -080061 Backtrace* backtrace;
Christopher Ferris17e91d42013-10-21 13:30:52 -070062 int32_t* now;
63 int32_t done;
64} dump_thread_t;
65
66extern "C" {
67// Prototypes for functions in the test library.
68int test_level_one(int, int, int, int, void (*)(void*), void*);
69
70int test_recursive_call(int, void (*)(void*), void*);
71}
72
73uint64_t NanoTime() {
74 struct timespec t = { 0, 0 };
75 clock_gettime(CLOCK_MONOTONIC, &t);
76 return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
77}
78
Christopher Ferris20303f82014-01-10 16:33:16 -080079void DumpFrames(Backtrace* backtrace) {
80 if (backtrace->NumFrames() == 0) {
Christopher Ferris17e91d42013-10-21 13:30:52 -070081 printf(" No frames to dump\n");
Christopher Ferris20303f82014-01-10 16:33:16 -080082 return;
83 }
84
85 for (size_t i = 0; i < backtrace->NumFrames(); i++) {
86 printf(" %s\n", backtrace->FormatFrameData(i).c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -070087 }
88}
89
90void WaitForStop(pid_t pid) {
91 uint64_t start = NanoTime();
92
93 siginfo_t si;
94 while (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) < 0 && (errno == EINTR || errno == ESRCH)) {
95 if ((NanoTime() - start) > NS_PER_SEC) {
96 printf("The process did not get to a stopping point in 1 second.\n");
97 break;
98 }
99 usleep(US_PER_MSEC);
100 }
101}
102
Christopher Ferris20303f82014-01-10 16:33:16 -0800103bool ReadyLevelBacktrace(Backtrace* backtrace) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700104 // See if test_level_four is in the backtrace.
105 bool found = false;
Christopher Ferris20303f82014-01-10 16:33:16 -0800106 for (size_t i = 0; i < backtrace->NumFrames(); i++) {
107 const backtrace_frame_data_t* frame = backtrace->GetFrame(i);
108 if (frame->func_name != NULL && strcmp(frame->func_name, "test_level_four") == 0) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700109 found = true;
110 break;
111 }
112 }
113
114 return found;
115}
116
Christopher Ferris20303f82014-01-10 16:33:16 -0800117void VerifyLevelDump(Backtrace* backtrace) {
118 ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0));
119 ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700120
121 // Look through the frames starting at the highest to find the
122 // frame we want.
123 size_t frame_num = 0;
Christopher Ferris20303f82014-01-10 16:33:16 -0800124 for (size_t i = backtrace->NumFrames()-1; i > 2; i--) {
125 if (backtrace->GetFrame(i)->func_name != NULL &&
126 strcmp(backtrace->GetFrame(i)->func_name, "test_level_one") == 0) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700127 frame_num = i;
128 break;
129 }
130 }
Christopher Ferris20303f82014-01-10 16:33:16 -0800131 ASSERT_LT(static_cast<size_t>(0), frame_num);
132 ASSERT_LE(static_cast<size_t>(3), frame_num);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700133
Christopher Ferris20303f82014-01-10 16:33:16 -0800134 ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num)->func_name);
135 ASSERT_STREQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one");
136 ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-1)->func_name);
137 ASSERT_STREQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two");
138 ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-2)->func_name);
139 ASSERT_STREQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three");
140 ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-3)->func_name);
141 ASSERT_STREQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four");
Christopher Ferris17e91d42013-10-21 13:30:52 -0700142}
143
144void VerifyLevelBacktrace(void*) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800145 UniquePtr<Backtrace> backtrace(
146 Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
147 ASSERT_TRUE(backtrace.get() != NULL);
148 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700149
Christopher Ferris20303f82014-01-10 16:33:16 -0800150 VerifyLevelDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700151}
152
Christopher Ferris20303f82014-01-10 16:33:16 -0800153bool ReadyMaxBacktrace(Backtrace* backtrace) {
154 return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700155}
156
Christopher Ferris20303f82014-01-10 16:33:16 -0800157void VerifyMaxDump(Backtrace* backtrace) {
158 ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700159 // Verify that the last frame is our recursive call.
Christopher Ferris20303f82014-01-10 16:33:16 -0800160 ASSERT_TRUE(NULL != backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name);
161 ASSERT_STREQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name,
Christopher Ferris17e91d42013-10-21 13:30:52 -0700162 "test_recursive_call");
163}
164
165void VerifyMaxBacktrace(void*) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800166 UniquePtr<Backtrace> backtrace(
167 Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
168 ASSERT_TRUE(backtrace.get() != NULL);
169 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700170
Christopher Ferris20303f82014-01-10 16:33:16 -0800171 VerifyMaxDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700172}
173
174void ThreadSetState(void* data) {
175 thread_t* thread = reinterpret_cast<thread_t*>(data);
176 android_atomic_acquire_store(1, &thread->state);
177 volatile int i = 0;
178 while (thread->state) {
179 i++;
180 }
181}
182
Christopher Ferris20303f82014-01-10 16:33:16 -0800183void VerifyThreadTest(pid_t tid, void (*VerifyFunc)(Backtrace*)) {
184 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
185 ASSERT_TRUE(backtrace.get() != NULL);
186 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700187
Christopher Ferris20303f82014-01-10 16:33:16 -0800188 VerifyFunc(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700189}
190
191bool WaitForNonZero(int32_t* value, uint64_t seconds) {
192 uint64_t start = NanoTime();
193 do {
194 if (android_atomic_acquire_load(value)) {
195 return true;
196 }
197 } while ((NanoTime() - start) < seconds * NS_PER_SEC);
198 return false;
199}
200
201TEST(libbacktrace, local_trace) {
202 ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, NULL), 0);
203}
204
205void VerifyIgnoreFrames(
Christopher Ferris20303f82014-01-10 16:33:16 -0800206 Backtrace* bt_all, Backtrace* bt_ign1,
207 Backtrace* bt_ign2, const char* cur_proc) {
208 EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1);
209 EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700210
211 // Check all of the frames are the same > the current frame.
212 bool check = (cur_proc == NULL);
Christopher Ferris20303f82014-01-10 16:33:16 -0800213 for (size_t i = 0; i < bt_ign2->NumFrames(); i++) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700214 if (check) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800215 EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc);
216 EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_ign1->GetFrame(i+1)->sp);
217 EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_ign1->GetFrame(i+1)->stack_size);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700218
Christopher Ferris20303f82014-01-10 16:33:16 -0800219 EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_all->GetFrame(i+2)->pc);
220 EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_all->GetFrame(i+2)->sp);
221 EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_all->GetFrame(i+2)->stack_size);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700222 }
Christopher Ferris20303f82014-01-10 16:33:16 -0800223 if (!check && bt_ign2->GetFrame(i)->func_name &&
224 strcmp(bt_ign2->GetFrame(i)->func_name, cur_proc) == 0) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700225 check = true;
226 }
227 }
228}
229
230void VerifyLevelIgnoreFrames(void*) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800231 UniquePtr<Backtrace> all(
232 Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
233 ASSERT_TRUE(all.get() != NULL);
234 ASSERT_TRUE(all->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700235
Christopher Ferris20303f82014-01-10 16:33:16 -0800236 UniquePtr<Backtrace> ign1(
237 Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
238 ASSERT_TRUE(ign1.get() != NULL);
239 ASSERT_TRUE(ign1->Unwind(1));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700240
Christopher Ferris20303f82014-01-10 16:33:16 -0800241 UniquePtr<Backtrace> ign2(
242 Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
243 ASSERT_TRUE(ign2.get() != NULL);
244 ASSERT_TRUE(ign2->Unwind(2));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700245
Christopher Ferris20303f82014-01-10 16:33:16 -0800246 VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
Christopher Ferris17e91d42013-10-21 13:30:52 -0700247}
248
249TEST(libbacktrace, local_trace_ignore_frames) {
250 ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, NULL), 0);
251}
252
253TEST(libbacktrace, local_max_trace) {
254 ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, NULL), 0);
255}
256
257void VerifyProcTest(pid_t pid, pid_t tid,
Christopher Ferris20303f82014-01-10 16:33:16 -0800258 bool (*ReadyFunc)(Backtrace*),
259 void (*VerifyFunc)(Backtrace*)) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700260 pid_t ptrace_tid;
261 if (tid < 0) {
262 ptrace_tid = pid;
263 } else {
264 ptrace_tid = tid;
265 }
266 uint64_t start = NanoTime();
267 bool verified = false;
268 do {
269 usleep(US_PER_MSEC);
270 if (ptrace(PTRACE_ATTACH, ptrace_tid, 0, 0) == 0) {
271 // Wait for the process to get to a stopping point.
272 WaitForStop(ptrace_tid);
273
Christopher Ferris20303f82014-01-10 16:33:16 -0800274 UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid));
275 ASSERT_TRUE(backtrace->Unwind(0));
276 ASSERT_TRUE(backtrace.get() != NULL);
277 if (ReadyFunc(backtrace.get())) {
278 VerifyFunc(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700279 verified = true;
280 }
Christopher Ferris20303f82014-01-10 16:33:16 -0800281
Christopher Ferris17e91d42013-10-21 13:30:52 -0700282 ASSERT_TRUE(ptrace(PTRACE_DETACH, ptrace_tid, 0, 0) == 0);
283 }
284 // If 5 seconds have passed, then we are done.
285 } while (!verified && (NanoTime() - start) <= 5 * NS_PER_SEC);
286 ASSERT_TRUE(verified);
287}
288
289TEST(libbacktrace, ptrace_trace) {
290 pid_t pid;
291 if ((pid = fork()) == 0) {
292 ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
293 exit(1);
294 }
Christopher Ferrisbc12d632013-11-12 10:54:16 -0800295 VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700296
297 kill(pid, SIGKILL);
298 int status;
299 ASSERT_EQ(waitpid(pid, &status, 0), pid);
300}
301
302TEST(libbacktrace, ptrace_max_trace) {
303 pid_t pid;
304 if ((pid = fork()) == 0) {
305 ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0);
306 exit(1);
307 }
Christopher Ferrisbc12d632013-11-12 10:54:16 -0800308 VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700309
310 kill(pid, SIGKILL);
311 int status;
312 ASSERT_EQ(waitpid(pid, &status, 0), pid);
313}
314
Christopher Ferris20303f82014-01-10 16:33:16 -0800315void VerifyProcessIgnoreFrames(Backtrace* bt_all) {
316 UniquePtr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
317 ASSERT_TRUE(ign1.get() != NULL);
318 ASSERT_TRUE(ign1->Unwind(1));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700319
Christopher Ferris20303f82014-01-10 16:33:16 -0800320 UniquePtr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
321 ASSERT_TRUE(ign2.get() != NULL);
322 ASSERT_TRUE(ign2->Unwind(2));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700323
Christopher Ferris20303f82014-01-10 16:33:16 -0800324 VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), NULL);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700325}
326
327TEST(libbacktrace, ptrace_ignore_frames) {
328 pid_t pid;
329 if ((pid = fork()) == 0) {
330 ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
331 exit(1);
332 }
Christopher Ferrisbc12d632013-11-12 10:54:16 -0800333 VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700334
335 kill(pid, SIGKILL);
336 int status;
337 ASSERT_EQ(waitpid(pid, &status, 0), pid);
338}
339
340// Create a process with multiple threads and dump all of the threads.
341void* PtraceThreadLevelRun(void*) {
342 EXPECT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
343 return NULL;
344}
345
346void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
347 // Get the list of tasks.
348 char task_path[128];
349 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
350
351 DIR* tasks_dir = opendir(task_path);
352 ASSERT_TRUE(tasks_dir != NULL);
353 struct dirent* entry;
354 while ((entry = readdir(tasks_dir)) != NULL) {
355 char* end;
356 pid_t tid = strtoul(entry->d_name, &end, 10);
357 if (*end == '\0') {
358 threads->push_back(tid);
359 }
360 }
361 closedir(tasks_dir);
362}
363
364TEST(libbacktrace, ptrace_threads) {
365 pid_t pid;
366 if ((pid = fork()) == 0) {
367 for (size_t i = 0; i < NUM_PTRACE_THREADS; i++) {
368 pthread_attr_t attr;
369 pthread_attr_init(&attr);
370 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
371
372 pthread_t thread;
373 ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, NULL) == 0);
374 }
375 ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
376 exit(1);
377 }
378
379 // Check to see that all of the threads are running before unwinding.
380 std::vector<pid_t> threads;
381 uint64_t start = NanoTime();
382 do {
383 usleep(US_PER_MSEC);
384 threads.clear();
385 GetThreads(pid, &threads);
386 } while ((threads.size() != NUM_PTRACE_THREADS + 1) &&
387 ((NanoTime() - start) <= 5 * NS_PER_SEC));
388 ASSERT_EQ(threads.size(), static_cast<size_t>(NUM_PTRACE_THREADS + 1));
389
390 ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
391 WaitForStop(pid);
392 for (std::vector<int>::const_iterator it = threads.begin(); it != threads.end(); ++it) {
393 // Skip the current forked process, we only care about the threads.
394 if (pid == *it) {
395 continue;
396 }
397 VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump);
398 }
399 ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
400
401 kill(pid, SIGKILL);
402 int status;
403 ASSERT_EQ(waitpid(pid, &status, 0), pid);
404}
405
406void VerifyLevelThread(void*) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800407 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
408 ASSERT_TRUE(backtrace.get() != NULL);
409 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700410
Christopher Ferris20303f82014-01-10 16:33:16 -0800411 VerifyLevelDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700412}
413
414TEST(libbacktrace, thread_current_level) {
415 ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, NULL), 0);
416}
417
418void VerifyMaxThread(void*) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800419 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
420 ASSERT_TRUE(backtrace.get() != NULL);
421 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700422
Christopher Ferris20303f82014-01-10 16:33:16 -0800423 VerifyMaxDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700424}
425
426TEST(libbacktrace, thread_current_max) {
427 ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, NULL), 0);
428}
429
430void* ThreadLevelRun(void* data) {
431 thread_t* thread = reinterpret_cast<thread_t*>(data);
432
433 thread->tid = gettid();
434 EXPECT_NE(test_level_one(1, 2, 3, 4, ThreadSetState, data), 0);
435 return NULL;
436}
437
438TEST(libbacktrace, thread_level_trace) {
439 pthread_attr_t attr;
440 pthread_attr_init(&attr);
441 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
442
443 thread_t thread_data = { 0, 0, 0 };
444 pthread_t thread;
445 ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
446
447 // Wait up to 2 seconds for the tid to be set.
448 ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
449
450 // Save the current signal action and make sure it is restored afterwards.
451 struct sigaction cur_action;
452 ASSERT_TRUE(sigaction(SIGURG, NULL, &cur_action) == 0);
453
Christopher Ferris20303f82014-01-10 16:33:16 -0800454 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
455 ASSERT_TRUE(backtrace.get() != NULL);
456 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700457
Christopher Ferris20303f82014-01-10 16:33:16 -0800458 VerifyLevelDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700459
460 // Tell the thread to exit its infinite loop.
461 android_atomic_acquire_store(0, &thread_data.state);
462
463 // Verify that the old action was restored.
464 struct sigaction new_action;
465 ASSERT_TRUE(sigaction(SIGURG, NULL, &new_action) == 0);
466 EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction);
467 EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags);
468}
469
470TEST(libbacktrace, thread_ignore_frames) {
471 pthread_attr_t attr;
472 pthread_attr_init(&attr);
473 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
474
475 thread_t thread_data = { 0, 0, 0 };
476 pthread_t thread;
477 ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
478
479 // Wait up to 2 seconds for the tid to be set.
480 ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
481
Christopher Ferris20303f82014-01-10 16:33:16 -0800482 UniquePtr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
483 ASSERT_TRUE(all.get() != NULL);
484 ASSERT_TRUE(all->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700485
Christopher Ferris20303f82014-01-10 16:33:16 -0800486 UniquePtr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
487 ASSERT_TRUE(ign1.get() != NULL);
488 ASSERT_TRUE(ign1->Unwind(1));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700489
Christopher Ferris20303f82014-01-10 16:33:16 -0800490 UniquePtr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
491 ASSERT_TRUE(ign2.get() != NULL);
492 ASSERT_TRUE(ign2->Unwind(2));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700493
Christopher Ferris20303f82014-01-10 16:33:16 -0800494 VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), NULL);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700495
496 // Tell the thread to exit its infinite loop.
497 android_atomic_acquire_store(0, &thread_data.state);
498}
499
500void* ThreadMaxRun(void* data) {
501 thread_t* thread = reinterpret_cast<thread_t*>(data);
502
503 thread->tid = gettid();
504 EXPECT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, ThreadSetState, data), 0);
505 return NULL;
506}
507
508TEST(libbacktrace, thread_max_trace) {
509 pthread_attr_t attr;
510 pthread_attr_init(&attr);
511 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
512
513 thread_t thread_data = { 0, 0, 0 };
514 pthread_t thread;
515 ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0);
516
517 // Wait for the tid to be set.
518 ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
519
Christopher Ferris20303f82014-01-10 16:33:16 -0800520 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
521 ASSERT_TRUE(backtrace.get() != NULL);
522 ASSERT_TRUE(backtrace->Unwind(0));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700523
Christopher Ferris20303f82014-01-10 16:33:16 -0800524 VerifyMaxDump(backtrace.get());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700525
526 // Tell the thread to exit its infinite loop.
527 android_atomic_acquire_store(0, &thread_data.state);
528}
529
530void* ThreadDump(void* data) {
531 dump_thread_t* dump = reinterpret_cast<dump_thread_t*>(data);
532 while (true) {
533 if (android_atomic_acquire_load(dump->now)) {
534 break;
535 }
536 }
537
Christopher Ferris17e91d42013-10-21 13:30:52 -0700538 // The status of the actual unwind will be checked elsewhere.
Christopher Ferris20303f82014-01-10 16:33:16 -0800539 dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid);
540 dump->backtrace->Unwind(0);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700541
542 android_atomic_acquire_store(1, &dump->done);
543
544 return NULL;
545}
546
547TEST(libbacktrace, thread_multiple_dump) {
548 // Dump NUM_THREADS simultaneously.
549 std::vector<thread_t> runners(NUM_THREADS);
550 std::vector<dump_thread_t> dumpers(NUM_THREADS);
551
552 pthread_attr_t attr;
553 pthread_attr_init(&attr);
554 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
555 for (size_t i = 0; i < NUM_THREADS; i++) {
556 // Launch the runners, they will spin in hard loops doing nothing.
557 runners[i].tid = 0;
558 runners[i].state = 0;
559 ASSERT_TRUE(pthread_create(&runners[i].threadId, &attr, ThreadMaxRun, &runners[i]) == 0);
560 }
561
562 // Wait for tids to be set.
563 for (std::vector<thread_t>::iterator it = runners.begin(); it != runners.end(); ++it) {
564 ASSERT_TRUE(WaitForNonZero(&it->state, 10));
565 }
566
567 // Start all of the dumpers at once, they will spin until they are signalled
568 // to begin their dump run.
569 int32_t dump_now = 0;
570 for (size_t i = 0; i < NUM_THREADS; i++) {
571 dumpers[i].thread.tid = runners[i].tid;
572 dumpers[i].thread.state = 0;
573 dumpers[i].done = 0;
574 dumpers[i].now = &dump_now;
575
576 ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0);
577 }
578
579 // Start all of the dumpers going at once.
580 android_atomic_acquire_store(1, &dump_now);
581
582 for (size_t i = 0; i < NUM_THREADS; i++) {
583 ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 10));
584
585 // Tell the runner thread to exit its infinite loop.
586 android_atomic_acquire_store(0, &runners[i].state);
587
Christopher Ferris20303f82014-01-10 16:33:16 -0800588 ASSERT_TRUE(dumpers[i].backtrace != NULL);
589 VerifyMaxDump(dumpers[i].backtrace);
590
591 delete dumpers[i].backtrace;
592 dumpers[i].backtrace = NULL;
Christopher Ferris17e91d42013-10-21 13:30:52 -0700593 }
594}
595
596TEST(libbacktrace, format_test) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800597 UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
598 ASSERT_TRUE(backtrace.get() != NULL);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700599
Christopher Ferris20303f82014-01-10 16:33:16 -0800600 backtrace_frame_data_t frame;
601 memset(&frame, 0, sizeof(backtrace_frame_data_t));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700602
Christopher Ferris20303f82014-01-10 16:33:16 -0800603 frame.num = 1;
Christopher Ferris17e91d42013-10-21 13:30:52 -0700604#if defined(__LP64__)
Christopher Ferris20303f82014-01-10 16:33:16 -0800605 EXPECT_STREQ("#01 pc 0000000000000000 <unknown>",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700606#else
Christopher Ferris20303f82014-01-10 16:33:16 -0800607 EXPECT_STREQ("#01 pc 00000000 <unknown>",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700608#endif
Christopher Ferris20303f82014-01-10 16:33:16 -0800609 backtrace->FormatFrameData(&frame).c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700610
Christopher Ferris20303f82014-01-10 16:33:16 -0800611 frame.pc = 0x12345678;
612 frame.map_name = "MapFake";
Christopher Ferris17e91d42013-10-21 13:30:52 -0700613#if defined(__LP64__)
Christopher Ferris20303f82014-01-10 16:33:16 -0800614 EXPECT_STREQ("#01 pc 0000000012345678 MapFake",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700615#else
Christopher Ferris20303f82014-01-10 16:33:16 -0800616 EXPECT_STREQ("#01 pc 12345678 MapFake",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700617#endif
Christopher Ferris20303f82014-01-10 16:33:16 -0800618 backtrace->FormatFrameData(&frame).c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700619
Christopher Ferris20303f82014-01-10 16:33:16 -0800620 frame.func_name = const_cast<char*>("ProcFake");
Christopher Ferris17e91d42013-10-21 13:30:52 -0700621#if defined(__LP64__)
Christopher Ferris20303f82014-01-10 16:33:16 -0800622 EXPECT_STREQ("#01 pc 0000000012345678 MapFake (ProcFake)",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700623#else
Christopher Ferris20303f82014-01-10 16:33:16 -0800624 EXPECT_STREQ("#01 pc 12345678 MapFake (ProcFake)",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700625#endif
Christopher Ferris20303f82014-01-10 16:33:16 -0800626 backtrace->FormatFrameData(&frame).c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700627
Christopher Ferris20303f82014-01-10 16:33:16 -0800628 frame.func_offset = 645;
Christopher Ferris17e91d42013-10-21 13:30:52 -0700629#if defined(__LP64__)
Christopher Ferris20303f82014-01-10 16:33:16 -0800630 EXPECT_STREQ("#01 pc 0000000012345678 MapFake (ProcFake+645)",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700631#else
Christopher Ferris20303f82014-01-10 16:33:16 -0800632 EXPECT_STREQ("#01 pc 12345678 MapFake (ProcFake+645)",
Christopher Ferris17e91d42013-10-21 13:30:52 -0700633#endif
Christopher Ferris20303f82014-01-10 16:33:16 -0800634 backtrace->FormatFrameData(&frame).c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700635}