1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <dlfcn.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <fcntl.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <time.h>
23*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
24*eb293b8fSAndroid Build Coastguard Worker
25*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
26*eb293b8fSAndroid Build Coastguard Worker
27*eb293b8fSAndroid Build Coastguard Worker #include <atomic>
28*eb293b8fSAndroid Build Coastguard Worker #include <string>
29*eb293b8fSAndroid Build Coastguard Worker #include <thread>
30*eb293b8fSAndroid Build Coastguard Worker #include <vector>
31*eb293b8fSAndroid Build Coastguard Worker
32*eb293b8fSAndroid Build Coastguard Worker #include <android-base/strings.h>
33*eb293b8fSAndroid Build Coastguard Worker #include <android-base/test_utils.h>
34*eb293b8fSAndroid Build Coastguard Worker #include <android-base/threads.h>
35*eb293b8fSAndroid Build Coastguard Worker
36*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/AndroidUnwinder.h>
37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Error.h>
38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineArm.h>
39*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineArm64.h>
40*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineRiscv64.h>
41*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineX86.h>
42*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineX86_64.h>
43*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
44*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsArm.h>
45*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsArm64.h>
46*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsGetLocal.h>
47*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsRiscv64.h>
48*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsX86.h>
49*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsX86_64.h>
50*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextArm.h>
51*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextArm64.h>
52*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextRiscv64.h>
53*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextX86.h>
54*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextX86_64.h>
55*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
56*eb293b8fSAndroid Build Coastguard Worker
57*eb293b8fSAndroid Build Coastguard Worker #include "ForkTest.h"
58*eb293b8fSAndroid Build Coastguard Worker #include "PidUtils.h"
59*eb293b8fSAndroid Build Coastguard Worker #include "TestUtils.h"
60*eb293b8fSAndroid Build Coastguard Worker
61*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
62*eb293b8fSAndroid Build Coastguard Worker
GetBacktrace(AndroidUnwinder & unwinder,std::vector<FrameData> & frames)63*eb293b8fSAndroid Build Coastguard Worker static std::string GetBacktrace(AndroidUnwinder& unwinder, std::vector<FrameData>& frames) {
64*eb293b8fSAndroid Build Coastguard Worker std::string backtrace_str;
65*eb293b8fSAndroid Build Coastguard Worker for (auto& frame : frames) {
66*eb293b8fSAndroid Build Coastguard Worker backtrace_str += unwinder.FormatFrame(frame) + '\n';
67*eb293b8fSAndroid Build Coastguard Worker }
68*eb293b8fSAndroid Build Coastguard Worker return backtrace_str;
69*eb293b8fSAndroid Build Coastguard Worker }
70*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidUnwinderDataTest,demangle_function_names)71*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidUnwinderDataTest, demangle_function_names) {
72*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
73*eb293b8fSAndroid Build Coastguard Worker
74*eb293b8fSAndroid Build Coastguard Worker // Add a few frames with and without demangled function names.
75*eb293b8fSAndroid Build Coastguard Worker data.frames.resize(4);
76*eb293b8fSAndroid Build Coastguard Worker data.frames[0].function_name = "no_demangle()";
77*eb293b8fSAndroid Build Coastguard Worker data.frames[1].function_name = "_Z4fakeb";
78*eb293b8fSAndroid Build Coastguard Worker data.frames[3].function_name = "_Z8demanglei";
79*eb293b8fSAndroid Build Coastguard Worker
80*eb293b8fSAndroid Build Coastguard Worker data.DemangleFunctionNames();
81*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("no_demangle()", data.frames[0].function_name);
82*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("fake(bool)", data.frames[1].function_name);
83*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("", data.frames[2].function_name);
84*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("demangle(int)", data.frames[3].function_name);
85*eb293b8fSAndroid Build Coastguard Worker
86*eb293b8fSAndroid Build Coastguard Worker // Make sure that this action is idempotent.
87*eb293b8fSAndroid Build Coastguard Worker data.DemangleFunctionNames();
88*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("no_demangle()", data.frames[0].function_name);
89*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("fake(bool)", data.frames[1].function_name);
90*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("", data.frames[2].function_name);
91*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("demangle(int)", data.frames[3].function_name);
92*eb293b8fSAndroid Build Coastguard Worker }
93*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidUnwinderDataTest,get_error_string)94*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidUnwinderDataTest, get_error_string) {
95*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
96*eb293b8fSAndroid Build Coastguard Worker
97*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("None", data.GetErrorString());
98*eb293b8fSAndroid Build Coastguard Worker data.error.code = ERROR_INVALID_ELF;
99*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Invalid Elf", data.GetErrorString());
100*eb293b8fSAndroid Build Coastguard Worker data.error.code = ERROR_MEMORY_INVALID;
101*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Memory Invalid", data.GetErrorString());
102*eb293b8fSAndroid Build Coastguard Worker data.error.address = 0x1000;
103*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Memory Invalid at address 0x1000", data.GetErrorString());
104*eb293b8fSAndroid Build Coastguard Worker }
105*eb293b8fSAndroid Build Coastguard Worker
106*eb293b8fSAndroid Build Coastguard Worker using AndroidUnwinderTest = ForkTest;
107*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidUnwinderTest,unwind_errors)108*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidUnwinderTest, unwind_errors) {
109*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
110*eb293b8fSAndroid Build Coastguard Worker
111*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
112*eb293b8fSAndroid Build Coastguard Worker void* ucontext = nullptr;
113*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(unwinder.Unwind(ucontext, data));
114*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
115*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Regs> regs;
116*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
117*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
118*eb293b8fSAndroid Build Coastguard Worker // Make sure that we are using a different arch from the
119*eb293b8fSAndroid Build Coastguard Worker // current arch.
120*eb293b8fSAndroid Build Coastguard Worker if (Regs::CurrentArch() == ARCH_ARM) {
121*eb293b8fSAndroid Build Coastguard Worker regs.reset(new RegsArm64);
122*eb293b8fSAndroid Build Coastguard Worker } else {
123*eb293b8fSAndroid Build Coastguard Worker regs.reset(new RegsArm);
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
126*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_BAD_ARCH, data.error.code);
127*eb293b8fSAndroid Build Coastguard Worker }
128*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidUnwinderTest,create)129*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidUnwinderTest, create) {
130*eb293b8fSAndroid Build Coastguard Worker // Verify the local unwinder object is created.
131*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<AndroidUnwinder> unwinder(AndroidUnwinder::Create(getpid()));
132*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
133*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder->Unwind(data));
134*eb293b8fSAndroid Build Coastguard Worker
135*eb293b8fSAndroid Build Coastguard Worker ForkAndWaitForPidState([this, &unwinder]() {
136*eb293b8fSAndroid Build Coastguard Worker // Verify the remote unwinder object is created.
137*eb293b8fSAndroid Build Coastguard Worker unwinder.reset(AndroidUnwinder::Create(pid_));
138*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
139*eb293b8fSAndroid Build Coastguard Worker if (!unwinder->Unwind(data)) {
140*eb293b8fSAndroid Build Coastguard Worker printf("Failed to unwind %s\n", data.GetErrorString().c_str());
141*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
142*eb293b8fSAndroid Build Coastguard Worker }
143*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_PASS;
144*eb293b8fSAndroid Build Coastguard Worker });
145*eb293b8fSAndroid Build Coastguard Worker }
146*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidUnwinderTest,initialize_fails)147*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidUnwinderTest, initialize_fails) {
148*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
149*eb293b8fSAndroid Build Coastguard Worker
150*eb293b8fSAndroid Build Coastguard Worker // Induce a failure in the initialize function by grabbing every
151*eb293b8fSAndroid Build Coastguard Worker // fd available.
152*eb293b8fSAndroid Build Coastguard Worker std::vector<android::base::unique_fd> fds;
153*eb293b8fSAndroid Build Coastguard Worker while (true) {
154*eb293b8fSAndroid Build Coastguard Worker auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY)));
155*eb293b8fSAndroid Build Coastguard Worker if (fd == -1) {
156*eb293b8fSAndroid Build Coastguard Worker break;
157*eb293b8fSAndroid Build Coastguard Worker }
158*eb293b8fSAndroid Build Coastguard Worker fds.emplace_back(std::move(fd));
159*eb293b8fSAndroid Build Coastguard Worker }
160*eb293b8fSAndroid Build Coastguard Worker
161*eb293b8fSAndroid Build Coastguard Worker ErrorData error;
162*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(unwinder.Initialize(error));
163*eb293b8fSAndroid Build Coastguard Worker
164*eb293b8fSAndroid Build Coastguard Worker // Make sure there is no crash when trying to unwind.
165*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
166*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(unwinder.Unwind(data));
167*eb293b8fSAndroid Build Coastguard Worker }
168*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidLocalUnwinderTest,initialize_before)169*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidLocalUnwinderTest, initialize_before) {
170*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
171*eb293b8fSAndroid Build Coastguard Worker ErrorData error;
172*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Initialize(error));
173*eb293b8fSAndroid Build Coastguard Worker
174*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
175*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
176*eb293b8fSAndroid Build Coastguard Worker }
177*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidLocalUnwinderTest,suffix_ignore)178*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidLocalUnwinderTest, suffix_ignore) {
179*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder(std::vector<std::string>{}, std::vector<std::string>{"so"});
180*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
181*eb293b8fSAndroid Build Coastguard Worker // This should work as long as the first frame is in the test executable.
182*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
183*eb293b8fSAndroid Build Coastguard Worker // Make sure the unwind doesn't include any .so frames.
184*eb293b8fSAndroid Build Coastguard Worker for (const auto& frame : data.frames) {
185*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(frame.map_info == nullptr ||
186*eb293b8fSAndroid Build Coastguard Worker !android::base::EndsWith(frame.map_info->name(), ".so"))
187*eb293b8fSAndroid Build Coastguard Worker << GetBacktrace(unwinder, data.frames);
188*eb293b8fSAndroid Build Coastguard Worker }
189*eb293b8fSAndroid Build Coastguard Worker }
190*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidUnwinderTest,verify_all_unwind_functions)191*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidUnwinderTest, verify_all_unwind_functions) {
192*eb293b8fSAndroid Build Coastguard Worker // Do not reuse the unwinder object to verify initialization is done
193*eb293b8fSAndroid Build Coastguard Worker // correctly.
194*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
195*eb293b8fSAndroid Build Coastguard Worker {
196*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
197*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
198*eb293b8fSAndroid Build Coastguard Worker }
199*eb293b8fSAndroid Build Coastguard Worker {
200*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
201*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(std::nullopt, data));
202*eb293b8fSAndroid Build Coastguard Worker }
203*eb293b8fSAndroid Build Coastguard Worker {
204*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
205*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(getpid(), data));
206*eb293b8fSAndroid Build Coastguard Worker }
207*eb293b8fSAndroid Build Coastguard Worker
208*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
209*eb293b8fSAndroid Build Coastguard Worker RegsGetLocal(regs.get());
210*eb293b8fSAndroid Build Coastguard Worker void* ucontext;
211*eb293b8fSAndroid Build Coastguard Worker switch (regs->Arch()) {
212*eb293b8fSAndroid Build Coastguard Worker case ARCH_ARM: {
213*eb293b8fSAndroid Build Coastguard Worker arm_ucontext_t* arm_ucontext =
214*eb293b8fSAndroid Build Coastguard Worker reinterpret_cast<arm_ucontext_t*>(malloc(sizeof(arm_ucontext_t)));
215*eb293b8fSAndroid Build Coastguard Worker ucontext = arm_ucontext;
216*eb293b8fSAndroid Build Coastguard Worker memcpy(&arm_ucontext->uc_mcontext.regs[0], regs->RawData(), ARM_REG_LAST * sizeof(uint32_t));
217*eb293b8fSAndroid Build Coastguard Worker } break;
218*eb293b8fSAndroid Build Coastguard Worker case ARCH_ARM64: {
219*eb293b8fSAndroid Build Coastguard Worker arm64_ucontext_t* arm64_ucontext =
220*eb293b8fSAndroid Build Coastguard Worker reinterpret_cast<arm64_ucontext_t*>(malloc(sizeof(arm64_ucontext_t)));
221*eb293b8fSAndroid Build Coastguard Worker ucontext = arm64_ucontext;
222*eb293b8fSAndroid Build Coastguard Worker memcpy(&arm64_ucontext->uc_mcontext.regs[0], regs->RawData(),
223*eb293b8fSAndroid Build Coastguard Worker ARM64_REG_LAST * sizeof(uint64_t));
224*eb293b8fSAndroid Build Coastguard Worker } break;
225*eb293b8fSAndroid Build Coastguard Worker case ARCH_X86: {
226*eb293b8fSAndroid Build Coastguard Worker x86_ucontext_t* x86_ucontext =
227*eb293b8fSAndroid Build Coastguard Worker reinterpret_cast<x86_ucontext_t*>(malloc(sizeof(x86_ucontext_t)));
228*eb293b8fSAndroid Build Coastguard Worker ucontext = x86_ucontext;
229*eb293b8fSAndroid Build Coastguard Worker RegsX86* regs_x86 = static_cast<RegsX86*>(regs.get());
230*eb293b8fSAndroid Build Coastguard Worker
231*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.edi = (*regs_x86)[X86_REG_EDI];
232*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.esi = (*regs_x86)[X86_REG_ESI];
233*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.ebp = (*regs_x86)[X86_REG_EBP];
234*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.esp = (*regs_x86)[X86_REG_ESP];
235*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.ebx = (*regs_x86)[X86_REG_EBX];
236*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.edx = (*regs_x86)[X86_REG_EDX];
237*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.ecx = (*regs_x86)[X86_REG_ECX];
238*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.eax = (*regs_x86)[X86_REG_EAX];
239*eb293b8fSAndroid Build Coastguard Worker x86_ucontext->uc_mcontext.eip = (*regs_x86)[X86_REG_EIP];
240*eb293b8fSAndroid Build Coastguard Worker } break;
241*eb293b8fSAndroid Build Coastguard Worker case ARCH_X86_64: {
242*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext_t* x86_64_ucontext =
243*eb293b8fSAndroid Build Coastguard Worker reinterpret_cast<x86_64_ucontext_t*>(malloc(sizeof(x86_64_ucontext_t)));
244*eb293b8fSAndroid Build Coastguard Worker ucontext = x86_64_ucontext;
245*eb293b8fSAndroid Build Coastguard Worker RegsX86_64* regs_x86_64 = static_cast<RegsX86_64*>(regs.get());
246*eb293b8fSAndroid Build Coastguard Worker
247*eb293b8fSAndroid Build Coastguard Worker memcpy(&x86_64_ucontext->uc_mcontext.r8, &(*regs_x86_64)[X86_64_REG_R8],
248*eb293b8fSAndroid Build Coastguard Worker 8 * sizeof(uint64_t));
249*eb293b8fSAndroid Build Coastguard Worker
250*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rdi = (*regs_x86_64)[X86_64_REG_RDI];
251*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rsi = (*regs_x86_64)[X86_64_REG_RSI];
252*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rbp = (*regs_x86_64)[X86_64_REG_RBP];
253*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rbx = (*regs_x86_64)[X86_64_REG_RBX];
254*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rdx = (*regs_x86_64)[X86_64_REG_RDX];
255*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rax = (*regs_x86_64)[X86_64_REG_RAX];
256*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rcx = (*regs_x86_64)[X86_64_REG_RCX];
257*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rsp = (*regs_x86_64)[X86_64_REG_RSP];
258*eb293b8fSAndroid Build Coastguard Worker x86_64_ucontext->uc_mcontext.rip = (*regs_x86_64)[X86_64_REG_RIP];
259*eb293b8fSAndroid Build Coastguard Worker } break;
260*eb293b8fSAndroid Build Coastguard Worker case ARCH_RISCV64: {
261*eb293b8fSAndroid Build Coastguard Worker riscv64_ucontext_t* riscv64_ucontext =
262*eb293b8fSAndroid Build Coastguard Worker reinterpret_cast<riscv64_ucontext_t*>(malloc(sizeof(riscv64_ucontext_t)));
263*eb293b8fSAndroid Build Coastguard Worker ucontext = riscv64_ucontext;
264*eb293b8fSAndroid Build Coastguard Worker memcpy(&riscv64_ucontext->uc_mcontext.__gregs, regs->RawData(),
265*eb293b8fSAndroid Build Coastguard Worker RISCV64_REG_REAL_COUNT * sizeof(uint64_t));
266*eb293b8fSAndroid Build Coastguard Worker } break;
267*eb293b8fSAndroid Build Coastguard Worker default:
268*eb293b8fSAndroid Build Coastguard Worker ucontext = nullptr;
269*eb293b8fSAndroid Build Coastguard Worker break;
270*eb293b8fSAndroid Build Coastguard Worker }
271*eb293b8fSAndroid Build Coastguard Worker
272*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder_with_ucontext;
273*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(ucontext != nullptr);
274*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder_with_ucontext.Unwind(ucontext, data));
275*eb293b8fSAndroid Build Coastguard Worker free(ucontext);
276*eb293b8fSAndroid Build Coastguard Worker
277*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder_with_regs;
278*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData reg_data;
279*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder_with_regs.Unwind(regs.get(), reg_data));
280*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(data.frames.size(), reg_data.frames.size());
281*eb293b8fSAndroid Build Coastguard Worker // Make sure all of the frame data is exactly the same.
282*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < data.frames.size(); i++) {
283*eb293b8fSAndroid Build Coastguard Worker SCOPED_TRACE("\nMismatch at Frame " + std::to_string(i) + "\nucontext trace:\n" +
284*eb293b8fSAndroid Build Coastguard Worker GetBacktrace(unwinder_with_ucontext, data.frames) + "\nregs trace:\n" +
285*eb293b8fSAndroid Build Coastguard Worker GetBacktrace(unwinder_with_regs, reg_data.frames));
286*eb293b8fSAndroid Build Coastguard Worker const auto& frame_context = data.frames[i];
287*eb293b8fSAndroid Build Coastguard Worker const auto& frame_reg = reg_data.frames[i];
288*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.num, frame_reg.num);
289*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.rel_pc, frame_reg.rel_pc);
290*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.pc, frame_reg.pc);
291*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.sp, frame_reg.sp);
292*eb293b8fSAndroid Build Coastguard Worker ASSERT_STREQ(frame_context.function_name.c_str(), frame_reg.function_name.c_str());
293*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.function_offset, frame_reg.function_offset);
294*eb293b8fSAndroid Build Coastguard Worker ASSERT_STREQ(frame_context.map_info->name().c_str(), frame_reg.map_info->name().c_str());
295*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.map_info->start(), frame_reg.map_info->start());
296*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frame_context.map_info->end(), frame_reg.map_info->end());
297*eb293b8fSAndroid Build Coastguard Worker }
298*eb293b8fSAndroid Build Coastguard Worker }
299*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidLocalUnwinderTest,unwind_current_thread)300*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidLocalUnwinderTest, unwind_current_thread) {
301*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
302*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
303*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
304*eb293b8fSAndroid Build Coastguard Worker // Verify that the libunwindstack.so does not appear in the first frame.
305*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(data.frames[0].map_info == nullptr ||
306*eb293b8fSAndroid Build Coastguard Worker !android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
307*eb293b8fSAndroid Build Coastguard Worker << "libunwindstack.so not removed properly\n"
308*eb293b8fSAndroid Build Coastguard Worker << GetBacktrace(unwinder, data.frames);
309*eb293b8fSAndroid Build Coastguard Worker }
310*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidLocalUnwinderTest,unwind_current_thread_show_all_frames)311*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidLocalUnwinderTest, unwind_current_thread_show_all_frames) {
312*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
313*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data(true);
314*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
315*eb293b8fSAndroid Build Coastguard Worker // Verify that the libunwindstack.so does appear in the first frame.
316*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(data.frames[0].map_info != nullptr &&
317*eb293b8fSAndroid Build Coastguard Worker android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
318*eb293b8fSAndroid Build Coastguard Worker << "libunwindstack.so was removed improperly\n"
319*eb293b8fSAndroid Build Coastguard Worker << GetBacktrace(unwinder, data.frames);
320*eb293b8fSAndroid Build Coastguard Worker }
321*eb293b8fSAndroid Build Coastguard Worker
ThreadBusyWait(std::atomic<pid_t> * tid,volatile bool * keep_running)322*eb293b8fSAndroid Build Coastguard Worker __attribute__((__noinline__)) extern "C" void ThreadBusyWait(std::atomic<pid_t>* tid,
323*eb293b8fSAndroid Build Coastguard Worker volatile bool* keep_running) {
324*eb293b8fSAndroid Build Coastguard Worker *tid = android::base::GetThreadId();
325*eb293b8fSAndroid Build Coastguard Worker while (*keep_running) {
326*eb293b8fSAndroid Build Coastguard Worker }
327*eb293b8fSAndroid Build Coastguard Worker }
328*eb293b8fSAndroid Build Coastguard Worker
TEST(AndroidLocalUnwinderTest,unwind_different_thread)329*eb293b8fSAndroid Build Coastguard Worker TEST(AndroidLocalUnwinderTest, unwind_different_thread) {
330*eb293b8fSAndroid Build Coastguard Worker std::atomic<pid_t> tid;
331*eb293b8fSAndroid Build Coastguard Worker volatile bool keep_running = true;
332*eb293b8fSAndroid Build Coastguard Worker std::thread thread([&tid, &keep_running] {
333*eb293b8fSAndroid Build Coastguard Worker ThreadBusyWait(&tid, &keep_running);
334*eb293b8fSAndroid Build Coastguard Worker return nullptr;
335*eb293b8fSAndroid Build Coastguard Worker });
336*eb293b8fSAndroid Build Coastguard Worker
337*eb293b8fSAndroid Build Coastguard Worker while (tid == 0) {
338*eb293b8fSAndroid Build Coastguard Worker }
339*eb293b8fSAndroid Build Coastguard Worker
340*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
341*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
342*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(tid, data));
343*eb293b8fSAndroid Build Coastguard Worker // Verify that we are unwinding the thread.
344*eb293b8fSAndroid Build Coastguard Worker
345*eb293b8fSAndroid Build Coastguard Worker // It's possible that ThreadBusyWait is not the lowest called function.
346*eb293b8fSAndroid Build Coastguard Worker // This can happen when running hwasan or if you run fast enough, you
347*eb293b8fSAndroid Build Coastguard Worker // can catch the code still in the atomic operator= function, but after
348*eb293b8fSAndroid Build Coastguard Worker // the tid is set. We really only care that the unwind sees you are in
349*eb293b8fSAndroid Build Coastguard Worker // ThreadBusyWait, so look for it specifically.
350*eb293b8fSAndroid Build Coastguard Worker size_t i = 0;
351*eb293b8fSAndroid Build Coastguard Worker for (; i < data.frames.size(); i++) {
352*eb293b8fSAndroid Build Coastguard Worker if (data.frames[i].function_name == "ThreadBusyWait") {
353*eb293b8fSAndroid Build Coastguard Worker break;
354*eb293b8fSAndroid Build Coastguard Worker }
355*eb293b8fSAndroid Build Coastguard Worker }
356*eb293b8fSAndroid Build Coastguard Worker ASSERT_NE(i, data.frames.size()) << "Cannot find ThreadBusyWait in backtrace\n"
357*eb293b8fSAndroid Build Coastguard Worker << GetBacktrace(unwinder, data.frames);
358*eb293b8fSAndroid Build Coastguard Worker ASSERT_NE(i + 1, data.frames.size())
359*eb293b8fSAndroid Build Coastguard Worker << "ThreadBusyWait function is the last frame of the unwind.\n"
360*eb293b8fSAndroid Build Coastguard Worker << GetBacktrace(unwinder, data.frames);
361*eb293b8fSAndroid Build Coastguard Worker
362*eb293b8fSAndroid Build Coastguard Worker // Allow the thread to terminate normally.
363*eb293b8fSAndroid Build Coastguard Worker keep_running = false;
364*eb293b8fSAndroid Build Coastguard Worker thread.join();
365*eb293b8fSAndroid Build Coastguard Worker }
366*eb293b8fSAndroid Build Coastguard Worker
367*eb293b8fSAndroid Build Coastguard Worker class AndroidRemoteUnwinderTest : public ForkTest {
368*eb293b8fSAndroid Build Coastguard Worker protected:
Verify(std::function<PidRunEnum (const FrameData & frame)> verify_func)369*eb293b8fSAndroid Build Coastguard Worker void Verify(std::function<PidRunEnum(const FrameData& frame)> verify_func) {
370*eb293b8fSAndroid Build Coastguard Worker ForkAndWaitForPidState([this, &verify_func]() {
371*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(pid_);
372*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
373*eb293b8fSAndroid Build Coastguard Worker if (!unwinder.Unwind(data)) {
374*eb293b8fSAndroid Build Coastguard Worker printf("Failed to unwind %s\n", data.GetErrorString().c_str());
375*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
376*eb293b8fSAndroid Build Coastguard Worker }
377*eb293b8fSAndroid Build Coastguard Worker const auto& frame = data.frames[0];
378*eb293b8fSAndroid Build Coastguard Worker return verify_func(frame);
379*eb293b8fSAndroid Build Coastguard Worker });
380*eb293b8fSAndroid Build Coastguard Worker }
381*eb293b8fSAndroid Build Coastguard Worker };
382*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidRemoteUnwinderTest,initialize_before)383*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidRemoteUnwinderTest, initialize_before) {
384*eb293b8fSAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(Fork());
385*eb293b8fSAndroid Build Coastguard Worker
386*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(pid_);
387*eb293b8fSAndroid Build Coastguard Worker ErrorData error;
388*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Initialize(error));
389*eb293b8fSAndroid Build Coastguard Worker
390*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
391*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
392*eb293b8fSAndroid Build Coastguard Worker }
393*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidRemoteUnwinderTest,skip_libraries)394*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidRemoteUnwinderTest, skip_libraries) {
395*eb293b8fSAndroid Build Coastguard Worker void* test_lib = GetTestLibHandle();
396*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(test_lib != nullptr);
397*eb293b8fSAndroid Build Coastguard Worker void (*wait_func)() = reinterpret_cast<void (*)()>(dlsym(test_lib, "WaitForever"));
398*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(wait_func != nullptr);
399*eb293b8fSAndroid Build Coastguard Worker
400*eb293b8fSAndroid Build Coastguard Worker SetForkFunc([wait_func]() { wait_func(); });
401*eb293b8fSAndroid Build Coastguard Worker Verify([this](const FrameData& frame) {
402*eb293b8fSAndroid Build Coastguard Worker // Make sure that the frame is in the dlopen'd library before proceeding.
403*eb293b8fSAndroid Build Coastguard Worker if (frame.map_info == nullptr ||
404*eb293b8fSAndroid Build Coastguard Worker !android::base::EndsWith(frame.map_info->name(), "/libunwindstack_local.so")) {
405*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_KEEP_GOING;
406*eb293b8fSAndroid Build Coastguard Worker }
407*eb293b8fSAndroid Build Coastguard Worker
408*eb293b8fSAndroid Build Coastguard Worker // Do an unwind removing the libunwindstack_local.so library.
409*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(pid_, std::vector<std::string>{"libunwindstack_local.so"});
410*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
411*eb293b8fSAndroid Build Coastguard Worker if (!unwinder.Unwind(data)) {
412*eb293b8fSAndroid Build Coastguard Worker printf("Failed to unwind %s\n", data.GetErrorString().c_str());
413*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
414*eb293b8fSAndroid Build Coastguard Worker }
415*eb293b8fSAndroid Build Coastguard Worker
416*eb293b8fSAndroid Build Coastguard Worker // Verify that library is properly ignored.
417*eb293b8fSAndroid Build Coastguard Worker if (android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack_local.so")) {
418*eb293b8fSAndroid Build Coastguard Worker printf("Failed to strip libunwindstack_local.so\n%s\n",
419*eb293b8fSAndroid Build Coastguard Worker GetBacktrace(unwinder, data.frames).c_str());
420*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
421*eb293b8fSAndroid Build Coastguard Worker }
422*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_PASS;
423*eb293b8fSAndroid Build Coastguard Worker });
424*eb293b8fSAndroid Build Coastguard Worker }
425*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidRemoteUnwinderTest,suffix_ignore)426*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidRemoteUnwinderTest, suffix_ignore) {
427*eb293b8fSAndroid Build Coastguard Worker Verify([this](const FrameData& frame) {
428*eb293b8fSAndroid Build Coastguard Worker // Wait until the forked process is no longer in libc.so.
429*eb293b8fSAndroid Build Coastguard Worker if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
430*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_KEEP_GOING;
431*eb293b8fSAndroid Build Coastguard Worker }
432*eb293b8fSAndroid Build Coastguard Worker
433*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(pid_, std::vector<std::string>{},
434*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string>{"so"});
435*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
436*eb293b8fSAndroid Build Coastguard Worker if (!unwinder.Unwind(data)) {
437*eb293b8fSAndroid Build Coastguard Worker printf("Failed to unwind %s\n", data.GetErrorString().c_str());
438*eb293b8fSAndroid Build Coastguard Worker
439*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder normal_unwinder(pid_);
440*eb293b8fSAndroid Build Coastguard Worker if (normal_unwinder.Unwind(data)) {
441*eb293b8fSAndroid Build Coastguard Worker printf("Full unwind %s\n", GetBacktrace(normal_unwinder, data.frames).c_str());
442*eb293b8fSAndroid Build Coastguard Worker }
443*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
444*eb293b8fSAndroid Build Coastguard Worker }
445*eb293b8fSAndroid Build Coastguard Worker
446*eb293b8fSAndroid Build Coastguard Worker // Make sure the unwind doesn't include any .so frames.
447*eb293b8fSAndroid Build Coastguard Worker for (const auto& frame : data.frames) {
448*eb293b8fSAndroid Build Coastguard Worker if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
449*eb293b8fSAndroid Build Coastguard Worker printf("Found unexpected .so frame\n%s\n", GetBacktrace(unwinder, data.frames).c_str());
450*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_FAIL;
451*eb293b8fSAndroid Build Coastguard Worker }
452*eb293b8fSAndroid Build Coastguard Worker }
453*eb293b8fSAndroid Build Coastguard Worker return PID_RUN_PASS;
454*eb293b8fSAndroid Build Coastguard Worker });
455*eb293b8fSAndroid Build Coastguard Worker }
456*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidRemoteUnwinderTest,remote_get_arch_ptrace_fails)457*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidRemoteUnwinderTest, remote_get_arch_ptrace_fails) {
458*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(getpid());
459*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
460*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(unwinder.Unwind(data));
461*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Ptrace Call Failed", data.GetErrorString());
462*eb293b8fSAndroid Build Coastguard Worker }
463*eb293b8fSAndroid Build Coastguard Worker
TEST_F(AndroidRemoteUnwinderTest,remote_get_ptrace_fails)464*eb293b8fSAndroid Build Coastguard Worker TEST_F(AndroidRemoteUnwinderTest, remote_get_ptrace_fails) {
465*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(getpid(), Regs::CurrentArch());
466*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
467*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(unwinder.Unwind(data));
468*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Ptrace Call Failed", data.GetErrorString());
469*eb293b8fSAndroid Build Coastguard Worker }
470*eb293b8fSAndroid Build Coastguard Worker
471*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
472