• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 <dlfcn.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <time.h>
22 #include <unistd.h>
23 
24 #include <gtest/gtest.h>
25 
26 #include <atomic>
27 #include <string>
28 #include <thread>
29 #include <vector>
30 
31 #include <android-base/strings.h>
32 #include <android-base/threads.h>
33 
34 #include <unwindstack/AndroidUnwinder.h>
35 #include <unwindstack/Error.h>
36 #include <unwindstack/Regs.h>
37 #include <unwindstack/RegsArm.h>
38 #include <unwindstack/RegsArm64.h>
39 #include <unwindstack/RegsGetLocal.h>
40 #include <unwindstack/RegsX86.h>
41 #include <unwindstack/RegsX86_64.h>
42 #include <unwindstack/UcontextArm.h>
43 #include <unwindstack/UcontextArm64.h>
44 #include <unwindstack/UcontextX86.h>
45 #include <unwindstack/UcontextX86_64.h>
46 #include <unwindstack/Unwinder.h>
47 
48 #include "PidUtils.h"
49 #include "TestUtils.h"
50 
51 namespace unwindstack {
52 
GetBacktrace(AndroidUnwinder & unwinder,std::vector<FrameData> & frames)53 static std::string GetBacktrace(AndroidUnwinder& unwinder, std::vector<FrameData>& frames) {
54   std::string backtrace_str;
55   for (auto& frame : frames) {
56     backtrace_str += unwinder.FormatFrame(frame) + '\n';
57   }
58   return backtrace_str;
59 }
60 
ForkWaitForever()61 static pid_t ForkWaitForever() {
62   pid_t pid;
63   if ((pid = fork()) == 0) {
64     // Do a loop that guarantees the terminating leaf frame will be in
65     // the test executable and not any other library function.
66     bool run = true;
67     while (run) {
68       DoNotOptimize(run = true);
69     }
70     exit(1);
71   }
72   return pid;
73 }
74 
TEST(AndroidUnwinderDataTest,demangle_function_names)75 TEST(AndroidUnwinderDataTest, demangle_function_names) {
76   AndroidUnwinderData data;
77 
78   // Add a few frames with and without demangled function names.
79   data.frames.resize(4);
80   data.frames[0].function_name = "no_demangle()";
81   data.frames[1].function_name = "_Z4fakeb";
82   data.frames[3].function_name = "_Z8demanglei";
83 
84   data.DemangleFunctionNames();
85   EXPECT_EQ("no_demangle()", data.frames[0].function_name);
86   EXPECT_EQ("fake(bool)", data.frames[1].function_name);
87   EXPECT_EQ("", data.frames[2].function_name);
88   EXPECT_EQ("demangle(int)", data.frames[3].function_name);
89 
90   // Make sure that this action is idempotent.
91   data.DemangleFunctionNames();
92   EXPECT_EQ("no_demangle()", data.frames[0].function_name);
93   EXPECT_EQ("fake(bool)", data.frames[1].function_name);
94   EXPECT_EQ("", data.frames[2].function_name);
95   EXPECT_EQ("demangle(int)", data.frames[3].function_name);
96 }
97 
TEST(AndroidUnwinderDataTest,get_error_string)98 TEST(AndroidUnwinderDataTest, get_error_string) {
99   AndroidUnwinderData data;
100 
101   EXPECT_EQ("None", data.GetErrorString());
102   data.error.code = ERROR_INVALID_ELF;
103   EXPECT_EQ("Invalid Elf", data.GetErrorString());
104   data.error.code = ERROR_MEMORY_INVALID;
105   EXPECT_EQ("Memory Invalid", data.GetErrorString());
106   data.error.address = 0x1000;
107   EXPECT_EQ("Memory Invalid at address 0x1000", data.GetErrorString());
108 }
109 
TEST(AndroidUnwinderTest,unwind_errors)110 TEST(AndroidUnwinderTest, unwind_errors) {
111   AndroidLocalUnwinder unwinder;
112 
113   AndroidUnwinderData data;
114   void* ucontext = nullptr;
115   EXPECT_FALSE(unwinder.Unwind(ucontext, data));
116   EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
117   std::unique_ptr<Regs> regs;
118   EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
119   EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
120   // Make sure that we are using a different arch from the
121   // current arch.
122   if (Regs::CurrentArch() == ARCH_ARM) {
123     regs.reset(new RegsArm64);
124   } else {
125     regs.reset(new RegsArm);
126   }
127   EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
128   EXPECT_EQ(ERROR_BAD_ARCH, data.error.code);
129 }
130 
TEST(AndroidUnwinderTest,create)131 TEST(AndroidUnwinderTest, create) {
132   // Verify the local unwinder object is created.
133   std::unique_ptr<AndroidUnwinder> unwinder(AndroidUnwinder::Create(getpid()));
134   AndroidUnwinderData data;
135   ASSERT_TRUE(unwinder->Unwind(data));
136 
137   pid_t pid = ForkWaitForever();
138   ASSERT_NE(-1, pid);
139   TestScopedPidReaper reap(pid);
140 
141   ASSERT_TRUE(RunWhenQuiesced(pid, false, [pid, &unwinder]() {
142     // Verify the remote unwinder object is created.
143     unwinder.reset(AndroidUnwinder::Create(pid));
144     AndroidUnwinderData data;
145     if (!unwinder->Unwind(data)) {
146       printf("Failed to unwind %s\n", data.GetErrorString().c_str());
147       return PID_RUN_FAIL;
148     }
149     return PID_RUN_PASS;
150   }));
151 }
152 
TEST(AndroidLocalUnwinderTest,initialize_before)153 TEST(AndroidLocalUnwinderTest, initialize_before) {
154   AndroidLocalUnwinder unwinder;
155   ErrorData error;
156   ASSERT_TRUE(unwinder.Initialize(error));
157 
158   AndroidUnwinderData data;
159   ASSERT_TRUE(unwinder.Unwind(data));
160 }
161 
TEST(AndroidLocalUnwinderTest,suffix_ignore)162 TEST(AndroidLocalUnwinderTest, suffix_ignore) {
163   AndroidLocalUnwinder unwinder(std::vector<std::string>{}, std::vector<std::string>{"so"});
164   AndroidUnwinderData data;
165   // This should work as long as the first frame is in the test executable.
166   ASSERT_TRUE(unwinder.Unwind(data));
167   // Make sure the unwind doesn't include any .so frames.
168   for (const auto& frame : data.frames) {
169     ASSERT_TRUE(frame.map_info == nullptr ||
170                 !android::base::EndsWith(frame.map_info->name(), ".so"))
171         << GetBacktrace(unwinder, data.frames);
172   }
173 }
174 
TEST(AndroidUnwinderTest,verify_all_unwind_functions)175 TEST(AndroidUnwinderTest, verify_all_unwind_functions) {
176   AndroidLocalUnwinder unwinder;
177   AndroidUnwinderData data;
178   ASSERT_TRUE(unwinder.Unwind(data));
179   ASSERT_TRUE(unwinder.Unwind(std::nullopt, data));
180   ASSERT_TRUE(unwinder.Unwind(getpid(), data));
181   std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
182   RegsGetLocal(regs.get());
183 
184   void* ucontext;
185   switch (regs->Arch()) {
186     case ARCH_ARM: {
187       arm_ucontext_t* arm_ucontext =
188           reinterpret_cast<arm_ucontext_t*>(malloc(sizeof(arm_ucontext_t)));
189       ucontext = arm_ucontext;
190       memcpy(&arm_ucontext->uc_mcontext.regs[0], regs->RawData(), ARM_REG_LAST * sizeof(uint32_t));
191     } break;
192     case ARCH_ARM64: {
193       arm64_ucontext_t* arm64_ucontext =
194           reinterpret_cast<arm64_ucontext_t*>(malloc(sizeof(arm64_ucontext_t)));
195       ucontext = arm64_ucontext;
196       memcpy(&arm64_ucontext->uc_mcontext.regs[0], regs->RawData(),
197              ARM64_REG_LAST * sizeof(uint64_t));
198     } break;
199     case ARCH_X86: {
200       x86_ucontext_t* x86_ucontext =
201           reinterpret_cast<x86_ucontext_t*>(malloc(sizeof(x86_ucontext_t)));
202       ucontext = x86_ucontext;
203       RegsX86* regs_x86 = static_cast<RegsX86*>(regs.get());
204 
205       x86_ucontext->uc_mcontext.edi = (*regs_x86)[X86_REG_EDI];
206       x86_ucontext->uc_mcontext.esi = (*regs_x86)[X86_REG_ESI];
207       x86_ucontext->uc_mcontext.ebp = (*regs_x86)[X86_REG_EBP];
208       x86_ucontext->uc_mcontext.esp = (*regs_x86)[X86_REG_ESP];
209       x86_ucontext->uc_mcontext.ebx = (*regs_x86)[X86_REG_EBX];
210       x86_ucontext->uc_mcontext.edx = (*regs_x86)[X86_REG_EDX];
211       x86_ucontext->uc_mcontext.ecx = (*regs_x86)[X86_REG_ECX];
212       x86_ucontext->uc_mcontext.eax = (*regs_x86)[X86_REG_EAX];
213       x86_ucontext->uc_mcontext.eip = (*regs_x86)[X86_REG_EIP];
214     } break;
215     case ARCH_X86_64: {
216       x86_64_ucontext_t* x86_64_ucontext =
217           reinterpret_cast<x86_64_ucontext_t*>(malloc(sizeof(x86_64_ucontext_t)));
218       ucontext = x86_64_ucontext;
219       RegsX86_64* regs_x86_64 = static_cast<RegsX86_64*>(regs.get());
220 
221       memcpy(&x86_64_ucontext->uc_mcontext.r8, &(*regs_x86_64)[X86_64_REG_R8],
222              8 * sizeof(uint64_t));
223 
224       x86_64_ucontext->uc_mcontext.rdi = (*regs_x86_64)[X86_64_REG_RDI];
225       x86_64_ucontext->uc_mcontext.rsi = (*regs_x86_64)[X86_64_REG_RSI];
226       x86_64_ucontext->uc_mcontext.rbp = (*regs_x86_64)[X86_64_REG_RBP];
227       x86_64_ucontext->uc_mcontext.rbx = (*regs_x86_64)[X86_64_REG_RBX];
228       x86_64_ucontext->uc_mcontext.rdx = (*regs_x86_64)[X86_64_REG_RDX];
229       x86_64_ucontext->uc_mcontext.rax = (*regs_x86_64)[X86_64_REG_RAX];
230       x86_64_ucontext->uc_mcontext.rcx = (*regs_x86_64)[X86_64_REG_RCX];
231       x86_64_ucontext->uc_mcontext.rsp = (*regs_x86_64)[X86_64_REG_RSP];
232       x86_64_ucontext->uc_mcontext.rip = (*regs_x86_64)[X86_64_REG_RIP];
233     } break;
234     default:
235       ucontext = nullptr;
236       break;
237   }
238   ASSERT_TRUE(ucontext != nullptr);
239   ASSERT_TRUE(unwinder.Unwind(ucontext, data));
240   free(ucontext);
241   AndroidUnwinderData reg_data;
242   ASSERT_TRUE(unwinder.Unwind(regs.get(), reg_data));
243   ASSERT_EQ(data.frames.size(), reg_data.frames.size());
244   // Make sure all of the frame data is exactly the same.
245   for (size_t i = 0; i < data.frames.size(); i++) {
246     SCOPED_TRACE("\nMismatch at Frame " + std::to_string(i) + "\nucontext trace:\n" +
247                  GetBacktrace(unwinder, data.frames) + "\nregs trace:\n" +
248                  GetBacktrace(unwinder, reg_data.frames));
249     const auto& frame_context = data.frames[i];
250     const auto& frame_reg = reg_data.frames[i];
251     ASSERT_EQ(frame_context.num, frame_reg.num);
252     ASSERT_EQ(frame_context.rel_pc, frame_reg.rel_pc);
253     ASSERT_EQ(frame_context.pc, frame_reg.pc);
254     ASSERT_EQ(frame_context.sp, frame_reg.sp);
255     ASSERT_STREQ(frame_context.function_name.c_str(), frame_reg.function_name.c_str());
256     ASSERT_EQ(frame_context.function_offset, frame_reg.function_offset);
257     ASSERT_EQ(frame_context.map_info.get(), frame_reg.map_info.get());
258   }
259 }
260 
TEST(AndroidLocalUnwinderTest,unwind_current_thread)261 TEST(AndroidLocalUnwinderTest, unwind_current_thread) {
262   AndroidLocalUnwinder unwinder;
263   AndroidUnwinderData data;
264   ASSERT_TRUE(unwinder.Unwind(data));
265   // Verify that the libunwindstack.so does not appear in the first frame.
266   ASSERT_TRUE(data.frames[0].map_info == nullptr ||
267               !android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
268       << "libunwindstack.so not removed properly\n"
269       << GetBacktrace(unwinder, data.frames);
270 }
271 
TEST(AndroidLocalUnwinderTest,unwind_current_thread_show_all_frames)272 TEST(AndroidLocalUnwinderTest, unwind_current_thread_show_all_frames) {
273   AndroidLocalUnwinder unwinder;
274   AndroidUnwinderData data(true);
275   ASSERT_TRUE(unwinder.Unwind(data));
276   // Verify that the libunwindstack.so does appear in the first frame.
277   ASSERT_TRUE(data.frames[0].map_info != nullptr &&
278               android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
279       << "libunwindstack.so was removed improperly\n"
280       << GetBacktrace(unwinder, data.frames);
281 }
282 
TEST(AndroidLocalUnwinderTest,unwind_different_thread)283 TEST(AndroidLocalUnwinderTest, unwind_different_thread) {
284   std::atomic<pid_t> tid;
285   std::atomic_bool keep_running = true;
286   std::thread thread([&tid, &keep_running] {
287     tid = android::base::GetThreadId();
288     while (keep_running) {
289     }
290     return nullptr;
291   });
292 
293   while (tid == 0) {
294   }
295 
296   {
297     AndroidLocalUnwinder unwinder;
298     AndroidUnwinderData data;
299     ASSERT_TRUE(unwinder.Unwind(data));
300     // Verify that the libunwindstack.so does not appear in the first frame.
301     ASSERT_TRUE(data.frames[0].map_info == nullptr ||
302                 !android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
303         << "libunwindstack.so not removed properly\n"
304         << GetBacktrace(unwinder, data.frames);
305   }
306 
307   {
308     AndroidLocalUnwinder unwinder;
309     AndroidUnwinderData data(true);
310     ASSERT_TRUE(unwinder.Unwind(data));
311     // Verify that the libunwindstack.so does appear in the first frame.
312     ASSERT_TRUE(data.frames[0].map_info != nullptr &&
313                 android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
314         << "libunwindstack.so was removed improperly\n"
315         << GetBacktrace(unwinder, data.frames);
316   }
317 
318   // Allow the thread to terminate normally.
319   keep_running = false;
320   thread.join();
321 }
322 
TEST(AndroidRemoteUnwinderTest,initialize_before)323 TEST(AndroidRemoteUnwinderTest, initialize_before) {
324   pid_t pid = ForkWaitForever();
325   ASSERT_NE(-1, pid);
326   TestScopedPidReaper reap(pid);
327 
328   ASSERT_TRUE(Attach(pid));
329 
330   AndroidRemoteUnwinder unwinder(pid);
331   ErrorData error;
332   ASSERT_TRUE(unwinder.Initialize(error));
333 
334   AndroidUnwinderData data;
335   ASSERT_TRUE(unwinder.Unwind(data));
336 
337   ASSERT_TRUE(Detach(pid));
338 }
339 
Verify(pid_t pid,std::function<PidRunEnum (const FrameData & frame)> fn)340 static bool Verify(pid_t pid, std::function<PidRunEnum(const FrameData& frame)> fn) {
341   return RunWhenQuiesced(pid, false, [pid, &fn]() {
342     AndroidRemoteUnwinder unwinder(pid);
343     AndroidUnwinderData data;
344     if (!unwinder.Unwind(data)) {
345       printf("Failed to unwind %s\n", data.GetErrorString().c_str());
346       return PID_RUN_FAIL;
347     }
348     const auto& frame = data.frames[0];
349     return fn(frame);
350   });
351 }
352 
TEST(AndroidRemoteUnwinderTest,skip_libraries)353 TEST(AndroidRemoteUnwinderTest, skip_libraries) {
354   void* test_lib = GetTestLibHandle();
355   ASSERT_TRUE(test_lib != nullptr);
356   int (*wait_func)() = reinterpret_cast<int (*)()>(dlsym(test_lib, "WaitForever"));
357   ASSERT_TRUE(wait_func != nullptr);
358 
359   pid_t pid;
360   if ((pid = fork()) == 0) {
361     DoNotOptimize(wait_func());
362     exit(0);
363   }
364   ASSERT_NE(-1, pid);
365   TestScopedPidReaper reap(pid);
366 
367   ASSERT_TRUE(Verify(pid, [pid](const FrameData& frame) {
368     // Make sure that the frame is in the dlopen'd library before proceeding.
369     if (frame.map_info == nullptr ||
370         !android::base::EndsWith(frame.map_info->name(), "/libunwindstack_local.so")) {
371       return PID_RUN_KEEP_GOING;
372     }
373 
374     // Do an unwind removing the libunwindstack_local.so library.
375     AndroidRemoteUnwinder unwinder(pid, std::vector<std::string>{"libunwindstack_local.so"});
376     AndroidUnwinderData data;
377     if (!unwinder.Unwind(data)) {
378       printf("Failed to unwind %s\n", data.GetErrorString().c_str());
379       return PID_RUN_FAIL;
380     }
381 
382     // Verify that library is properly ignored.
383     if (android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack_local.so")) {
384       printf("Failed to strip libunwindstack_local.so\n%s\n",
385              GetBacktrace(unwinder, data.frames).c_str());
386       return PID_RUN_FAIL;
387     }
388     return PID_RUN_PASS;
389   }));
390 }
391 
TEST(AndroidRemoteUnwinderTest,suffix_ignore)392 TEST(AndroidRemoteUnwinderTest, suffix_ignore) {
393   pid_t pid = ForkWaitForever();
394   ASSERT_NE(-1, pid);
395   TestScopedPidReaper reap(pid);
396 
397   ASSERT_TRUE(Verify(pid, [pid](const FrameData& frame) {
398     // Wait until the forked process is no longer in libc.so.
399     if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
400       return PID_RUN_KEEP_GOING;
401     }
402 
403     AndroidRemoteUnwinder unwinder(pid, std::vector<std::string>{}, std::vector<std::string>{"so"});
404     AndroidUnwinderData data;
405     if (!unwinder.Unwind(data)) {
406       printf("Failed to unwind %s\n", data.GetErrorString().c_str());
407 
408       AndroidRemoteUnwinder normal_unwinder(pid);
409       if (normal_unwinder.Unwind(data)) {
410         printf("Full unwind %s\n", GetBacktrace(normal_unwinder, data.frames).c_str());
411       }
412       return PID_RUN_FAIL;
413     }
414 
415     // Make sure the unwind doesn't include any .so frames.
416     for (const auto& frame : data.frames) {
417       if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
418         printf("Found unexpected .so frame\n%s\n", GetBacktrace(unwinder, data.frames).c_str());
419         return PID_RUN_FAIL;
420       }
421     }
422     return PID_RUN_PASS;
423   }));
424 }
425 
426 }  // namespace unwindstack
427