1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2019 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 #define _GNU_SOURCE 1
18*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
20*eb293b8fSAndroid Build Coastguard Worker
21*eb293b8fSAndroid Build Coastguard Worker #include <string>
22*eb293b8fSAndroid Build Coastguard Worker
23*eb293b8fSAndroid Build Coastguard Worker #if defined(__BIONIC__)
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 <unwindstack/AndroidUnwinder.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfSection.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/ElfInterface.h>
31*eb293b8fSAndroid Build Coastguard Worker
32*eb293b8fSAndroid Build Coastguard Worker #include "ForkTest.h"
33*eb293b8fSAndroid Build Coastguard Worker
34*eb293b8fSAndroid Build Coastguard Worker // This test is specific to bionic to verify that __libc_init is
35*eb293b8fSAndroid Build Coastguard Worker // properly setting the return address to undefined so that the
36*eb293b8fSAndroid Build Coastguard Worker // unwind properly terminates.
37*eb293b8fSAndroid Build Coastguard Worker
38*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
39*eb293b8fSAndroid Build Coastguard Worker
40*eb293b8fSAndroid Build Coastguard Worker using VerifyBionicTermination = ForkTest;
41*eb293b8fSAndroid Build Coastguard Worker
DumpFrames(const AndroidUnwinderData & data,AndroidUnwinder & unwinder)42*eb293b8fSAndroid Build Coastguard Worker static std::string DumpFrames(const AndroidUnwinderData& data, AndroidUnwinder& unwinder) {
43*eb293b8fSAndroid Build Coastguard Worker // Init this way so that the first frame of the backtrace starts on a new line.
44*eb293b8fSAndroid Build Coastguard Worker std::string unwind("\n");
45*eb293b8fSAndroid Build Coastguard Worker for (auto& frame : data.frames) {
46*eb293b8fSAndroid Build Coastguard Worker unwind += unwinder.FormatFrame(frame) + '\n';
47*eb293b8fSAndroid Build Coastguard Worker }
48*eb293b8fSAndroid Build Coastguard Worker return unwind;
49*eb293b8fSAndroid Build Coastguard Worker }
50*eb293b8fSAndroid Build Coastguard Worker
GetReturnAddressLocation(uint64_t rel_pc,DwarfSection * section)51*eb293b8fSAndroid Build Coastguard Worker static DwarfLocationEnum GetReturnAddressLocation(uint64_t rel_pc, DwarfSection* section) {
52*eb293b8fSAndroid Build Coastguard Worker if (section == nullptr) {
53*eb293b8fSAndroid Build Coastguard Worker return DWARF_LOCATION_INVALID;
54*eb293b8fSAndroid Build Coastguard Worker }
55*eb293b8fSAndroid Build Coastguard Worker
56*eb293b8fSAndroid Build Coastguard Worker const DwarfFde* fde = section->GetFdeFromPc(rel_pc);
57*eb293b8fSAndroid Build Coastguard Worker if (fde == nullptr || fde->cie == nullptr) {
58*eb293b8fSAndroid Build Coastguard Worker return DWARF_LOCATION_INVALID;
59*eb293b8fSAndroid Build Coastguard Worker }
60*eb293b8fSAndroid Build Coastguard Worker DwarfLocations regs;
61*eb293b8fSAndroid Build Coastguard Worker if (!section->GetCfaLocationInfo(rel_pc, fde, ®s, ARCH_UNKNOWN)) {
62*eb293b8fSAndroid Build Coastguard Worker return DWARF_LOCATION_INVALID;
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker
65*eb293b8fSAndroid Build Coastguard Worker auto reg_entry = regs.find(fde->cie->return_address_register);
66*eb293b8fSAndroid Build Coastguard Worker if (reg_entry == regs.end()) {
67*eb293b8fSAndroid Build Coastguard Worker return DWARF_LOCATION_INVALID;
68*eb293b8fSAndroid Build Coastguard Worker }
69*eb293b8fSAndroid Build Coastguard Worker return reg_entry->second.type;
70*eb293b8fSAndroid Build Coastguard Worker }
71*eb293b8fSAndroid Build Coastguard Worker
VerifyReturnAddress(const FrameData & frame)72*eb293b8fSAndroid Build Coastguard Worker static void VerifyReturnAddress(const FrameData& frame) {
73*eb293b8fSAndroid Build Coastguard Worker // Now go and find information about the register data and verify that the relative pc results in
74*eb293b8fSAndroid Build Coastguard Worker // an undefined register.
75*eb293b8fSAndroid Build Coastguard Worker auto file_memory = Memory::CreateFileMemory(frame.map_info->name(), 0);
76*eb293b8fSAndroid Build Coastguard Worker Elf elf(file_memory);
77*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(frame.map_info != nullptr);
78*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_info->name().c_str();
79*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_info->name().c_str() << " is not valid.";
80*eb293b8fSAndroid Build Coastguard Worker ElfInterface* interface = elf.interface();
81*eb293b8fSAndroid Build Coastguard Worker
82*eb293b8fSAndroid Build Coastguard Worker // Only check the eh_frame and the debug_frame since the undefined register
83*eb293b8fSAndroid Build Coastguard Worker // is set using a cfi directive.
84*eb293b8fSAndroid Build Coastguard Worker // Check debug_frame first, then eh_frame since debug_frame always
85*eb293b8fSAndroid Build Coastguard Worker // contains the most specific data.
86*eb293b8fSAndroid Build Coastguard Worker DwarfLocationEnum location = GetReturnAddressLocation(frame.rel_pc, interface->debug_frame());
87*eb293b8fSAndroid Build Coastguard Worker if (location == DWARF_LOCATION_UNDEFINED) {
88*eb293b8fSAndroid Build Coastguard Worker return;
89*eb293b8fSAndroid Build Coastguard Worker }
90*eb293b8fSAndroid Build Coastguard Worker
91*eb293b8fSAndroid Build Coastguard Worker location = GetReturnAddressLocation(frame.rel_pc, interface->eh_frame());
92*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location);
93*eb293b8fSAndroid Build Coastguard Worker }
94*eb293b8fSAndroid Build Coastguard Worker
95*eb293b8fSAndroid Build Coastguard Worker // This assumes that the function starts from the main thread, and that the
96*eb293b8fSAndroid Build Coastguard Worker // libc.so on device will include symbols so that function names can
97*eb293b8fSAndroid Build Coastguard Worker // be resolved.
VerifyLibcInitTerminate(AndroidUnwinder & unwinder)98*eb293b8fSAndroid Build Coastguard Worker static void VerifyLibcInitTerminate(AndroidUnwinder& unwinder) {
99*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData data;
100*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(unwinder.Unwind(data));
101*eb293b8fSAndroid Build Coastguard Worker
102*eb293b8fSAndroid Build Coastguard Worker SCOPED_TRACE(DumpFrames(data, unwinder));
103*eb293b8fSAndroid Build Coastguard Worker
104*eb293b8fSAndroid Build Coastguard Worker // Look for the frame that includes __libc_init, there should only
105*eb293b8fSAndroid Build Coastguard Worker // be one and it should be the last.
106*eb293b8fSAndroid Build Coastguard Worker bool found = false;
107*eb293b8fSAndroid Build Coastguard Worker const std::vector<FrameData>& frames = data.frames;
108*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < frames.size(); i++) {
109*eb293b8fSAndroid Build Coastguard Worker const FrameData& frame = frames[i];
110*eb293b8fSAndroid Build Coastguard Worker if (frame.function_name == "__libc_init" && frame.map_info != nullptr &&
111*eb293b8fSAndroid Build Coastguard Worker !frame.map_info->name().empty() &&
112*eb293b8fSAndroid Build Coastguard Worker std::string("libc.so") == basename(frame.map_info->name().c_str())) {
113*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(frames.size(), i + 1) << "__libc_init is not last frame.";
114*eb293b8fSAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(VerifyReturnAddress(frame));
115*eb293b8fSAndroid Build Coastguard Worker found = true;
116*eb293b8fSAndroid Build Coastguard Worker }
117*eb293b8fSAndroid Build Coastguard Worker }
118*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(found) << "Unable to find libc.so:__libc_init frame\n";
119*eb293b8fSAndroid Build Coastguard Worker }
120*eb293b8fSAndroid Build Coastguard Worker
TEST_F(VerifyBionicTermination,local_terminate)121*eb293b8fSAndroid Build Coastguard Worker TEST_F(VerifyBionicTermination, local_terminate) {
122*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder unwinder;
123*eb293b8fSAndroid Build Coastguard Worker VerifyLibcInitTerminate(unwinder);
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker
TEST_F(VerifyBionicTermination,remote_terminate)126*eb293b8fSAndroid Build Coastguard Worker TEST_F(VerifyBionicTermination, remote_terminate) {
127*eb293b8fSAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(Fork());
128*eb293b8fSAndroid Build Coastguard Worker
129*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder unwinder(pid_);
130*eb293b8fSAndroid Build Coastguard Worker VerifyLibcInitTerminate(unwinder);
131*eb293b8fSAndroid Build Coastguard Worker }
132*eb293b8fSAndroid Build Coastguard Worker
133*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
134*eb293b8fSAndroid Build Coastguard Worker
135*eb293b8fSAndroid Build Coastguard Worker #endif
136