blob: 6155c9bd02e10d2f9a171cfce62e20e0c0b31fcf [file] [log] [blame]
Christopher Ferris7fb22872013-09-27 12:43:15 -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 <stdio.h>
18#include <stdlib.h>
19#include <stdbool.h>
20#include <string.h>
21#include <sys/types.h>
22#include <signal.h>
23#include <sys/ptrace.h>
24#include <sys/wait.h>
Christopher Ferrisa16a4e12013-10-01 17:54:11 -070025#include <errno.h>
Christopher Ferris7fb22872013-09-27 12:43:15 -070026#include <unistd.h>
27#include <inttypes.h>
28
29#include <backtrace/backtrace.h>
30
31#define FINISH(pid) dump_frames(&backtrace); if (pid < 0) exit(1); else return false;
32
Christopher Ferrisa16a4e12013-10-01 17:54:11 -070033#define WAIT_INTERVAL_USECS 1000
34
Christopher Ferris7fb22872013-09-27 12:43:15 -070035// Prototypes for functions in the test library.
36int test_level_one(int, int, int, int, bool (*)(pid_t));
37
38int test_recursive_call(int, bool (*)(pid_t));
39
40void dump_frames(const backtrace_t* backtrace) {
41 for (size_t i = 0; i < backtrace->num_frames; i++) {
42 printf("%zu ", i);
43 if (backtrace->frames[i].map_name) {
44 printf("%s", backtrace->frames[i].map_name);
45 } else {
46 printf("<unknown>");
47 }
48 if (backtrace->frames[i].proc_name) {
49 printf(" %s", backtrace->frames[i].proc_name);
50 if (backtrace->frames[i].proc_offset) {
51 printf("+%" PRIuPTR, backtrace->frames[i].proc_offset);
52 }
53 }
54 printf("\n");
55 }
56}
57
Christopher Ferrisa16a4e12013-10-01 17:54:11 -070058void wait_for_stop(pid_t pid, size_t max_usecs_to_wait) {
59 siginfo_t si;
60 size_t usecs_waited = 0;
61
62 while (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) < 0 && (errno == EINTR || errno == ESRCH)) {
63 if (usecs_waited >= max_usecs_to_wait) {
64 printf("The process did not get to a stopping point in %zu usecs.\n",
65 usecs_waited);
66 break;
67 }
68 usleep(WAIT_INTERVAL_USECS);
69 usecs_waited += WAIT_INTERVAL_USECS;
70 }
71}
72
Christopher Ferris7fb22872013-09-27 12:43:15 -070073bool check_frame(const backtrace_t* backtrace, size_t frame_num,
74 const char* expected_name) {
75 if (backtrace->frames[frame_num].proc_name == NULL) {
76 printf(" Frame %zu function name expected %s, real value is NULL.\n",
77 frame_num, expected_name);
78 return false;
79 }
80 if (strcmp(backtrace->frames[frame_num].proc_name, expected_name) != 0) {
81 printf(" Frame %zu function name expected %s, real value is %s.\n",
82 frame_num, expected_name, backtrace->frames[frame_num].proc_name);
83 return false;
84 }
85 return true;
86}
87
88bool verify_level_backtrace(pid_t pid) {
89 const char* test_type;
90 if (pid < 0) {
91 test_type = "current";
92 } else {
93 test_type = "running";
94 }
95
96 backtrace_t backtrace;
97 if (!backtrace_get_data(&backtrace, pid)) {
98 printf(" backtrace_get_data failed on %s process.\n", test_type);
99 FINISH(pid);
100 }
101
102 if (backtrace.num_frames == 0) {
103 printf(" backtrace_get_data returned no frames for %s process.\n",
104 test_type);
105 FINISH(pid);
106 }
107
108 // Look through the frames starting at the highest to find the
109 // frame we want.
110 size_t frame_num = 0;
111 for (size_t i = backtrace.num_frames-1; i > 2; i--) {
112 if (backtrace.frames[i].proc_name != NULL &&
113 strcmp(backtrace.frames[i].proc_name, "test_level_one") == 0) {
114 frame_num = i;
115 break;
116 }
117 }
118 if (!frame_num) {
119 printf(" backtrace_get_data did not include the test_level_one frame.\n");
120 FINISH(pid);
121 }
122
123 if (!check_frame(&backtrace, frame_num, "test_level_one")) {
124 FINISH(pid);
125 }
126 if (!check_frame(&backtrace, frame_num-1, "test_level_two")) {
127 FINISH(pid);
128 }
129 if (!check_frame(&backtrace, frame_num-2, "test_level_three")) {
130 FINISH(pid);
131 }
132 if (!check_frame(&backtrace, frame_num-3, "test_level_four")) {
133 FINISH(pid);
134 }
135 backtrace_free_data(&backtrace);
136
137 return true;
138}
139
140bool verify_max_backtrace(pid_t pid) {
141 const char* test_type;
142 if (pid < 0) {
143 test_type = "current";
144 } else {
145 test_type = "running";
146 }
147
148 backtrace_t backtrace;
149 if (!backtrace_get_data(&backtrace, pid)) {
150 printf(" backtrace_get_data failed on %s process.\n", test_type);
151 FINISH(pid);
152 }
153
154 if (backtrace.num_frames != MAX_BACKTRACE_FRAMES) {
155 printf(" backtrace_get_data %s process max frame check failed:\n",
156 test_type);
157 printf(" Expected num frames to be %zu, found %zu\n",
158 MAX_BACKTRACE_FRAMES, backtrace.num_frames);
159 FINISH(pid);
160 }
161 backtrace_free_data(&backtrace);
162
163 return true;
164}
165
166void verify_proc_test(pid_t pid, bool (*verify_func)(pid_t)) {
167 printf(" Waiting 5 seconds for process to get to infinite loop.\n");
168 sleep(5);
169 if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) {
170 printf("Failed to attach to pid %d\n", pid);
171 kill(pid, SIGKILL);
172 exit(1);
173 }
Christopher Ferrisa16a4e12013-10-01 17:54:11 -0700174
175 // Wait up to 1 second for the process to get to a point that we can trace it.
176 wait_for_stop(pid, 1000000);
177
Christopher Ferris7fb22872013-09-27 12:43:15 -0700178 bool pass = verify_func(pid);
179 if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) {
180 printf("Failed to detach from pid %d\n", pid);
181 kill(pid, SIGKILL);
182 exit(1);
183 }
184
185 kill(pid, SIGKILL);
186 int status;
187 if (waitpid(pid, &status, 0) != pid) {
188 printf("Forked process did not terminate properly.\n");
189 exit(1);
190 }
191
192 if (!pass) {
193 exit(1);
194 }
195}
196
197int main() {
198 printf("Running level test on current process...\n");
199 int value = test_level_one(1, 2, 3, 4, verify_level_backtrace);
200 if (value == 0) {
201 printf("This should never happen.\n");
202 exit(1);
203 }
204 printf(" Passed.\n");
205
206 printf("Running max level test on current process...\n");
207 value = test_recursive_call(MAX_BACKTRACE_FRAMES+10, verify_max_backtrace);
208 if (value == 0) {
209 printf("This should never happen.\n");
210 exit(1);
211 }
212 printf(" Passed.\n");
213
214 printf("Running level test on process...\n");
215 pid_t pid;
216 if ((pid = fork()) == 0) {
217 value = test_level_one(1, 2, 3, 4, NULL);
218 if (value == 0) {
219 printf("This should never happen.\n");
220 }
221 exit(1);
222 }
223 verify_proc_test(pid, verify_level_backtrace);
224 printf(" Passed.\n");
225
226 printf("Running max frame test on process...\n");
227 if ((pid = fork()) == 0) {
228 value = test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL);
229 if (value == 0) {
230 printf("This should never happen.\n");
231 }
232 exit(1);
233 }
234 verify_proc_test(pid, verify_max_backtrace);
235 printf(" Passed.\n");
236
237 printf("All tests passed.\n");
238 return 0;
239}