1/* 2 * Copyright (C) 2015 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 "dwarf_unwind.h" 18 19#include <ucontext.h> 20 21#include <backtrace/Backtrace.h> 22#include <android-base/logging.h> 23 24#include "thread_tree.h" 25 26#define SetUContextReg(dst, perf_regno) \ 27 do { \ 28 uint64_t value; \ 29 if (GetRegValue(regs, perf_regno, &value)) { \ 30 (dst) = value; \ 31 } \ 32 } while (0) 33 34static ucontext_t BuildUContextFromRegs(const RegSet& regs __attribute__((unused))) { 35 ucontext_t ucontext; 36 memset(&ucontext, 0, sizeof(ucontext)); 37#if defined(__i386__) 38 SetUContextReg(ucontext.uc_mcontext.gregs[REG_GS], PERF_REG_X86_GS); 39 SetUContextReg(ucontext.uc_mcontext.gregs[REG_FS], PERF_REG_X86_FS); 40 SetUContextReg(ucontext.uc_mcontext.gregs[REG_ES], PERF_REG_X86_ES); 41 SetUContextReg(ucontext.uc_mcontext.gregs[REG_DS], PERF_REG_X86_DS); 42 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EAX], PERF_REG_X86_AX); 43 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EBX], PERF_REG_X86_BX); 44 SetUContextReg(ucontext.uc_mcontext.gregs[REG_ECX], PERF_REG_X86_CX); 45 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EDX], PERF_REG_X86_DX); 46 SetUContextReg(ucontext.uc_mcontext.gregs[REG_ESI], PERF_REG_X86_SI); 47 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EDI], PERF_REG_X86_DI); 48 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EBP], PERF_REG_X86_BP); 49 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EIP], PERF_REG_X86_IP); 50 SetUContextReg(ucontext.uc_mcontext.gregs[REG_ESP], PERF_REG_X86_SP); 51 SetUContextReg(ucontext.uc_mcontext.gregs[REG_CS], PERF_REG_X86_CS); 52 SetUContextReg(ucontext.uc_mcontext.gregs[REG_EFL], PERF_REG_X86_FLAGS); 53 SetUContextReg(ucontext.uc_mcontext.gregs[REG_SS], PERF_REG_X86_SS); 54#elif defined(__x86_64__) 55 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R8], PERF_REG_X86_R8); 56 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R9], PERF_REG_X86_R9); 57 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R10], PERF_REG_X86_R10); 58 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R11], PERF_REG_X86_R11); 59 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R12], PERF_REG_X86_R12); 60 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R13], PERF_REG_X86_R13); 61 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R14], PERF_REG_X86_R14); 62 SetUContextReg(ucontext.uc_mcontext.gregs[REG_R15], PERF_REG_X86_R15); 63 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RDI], PERF_REG_X86_DI); 64 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RSI], PERF_REG_X86_SI); 65 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RBP], PERF_REG_X86_BP); 66 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RBX], PERF_REG_X86_BX); 67 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RDX], PERF_REG_X86_DX); 68 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RAX], PERF_REG_X86_AX); 69 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RCX], PERF_REG_X86_CX); 70 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RSP], PERF_REG_X86_SP); 71 SetUContextReg(ucontext.uc_mcontext.gregs[REG_RIP], PERF_REG_X86_IP); 72#elif defined(__aarch64__) 73 for (size_t i = PERF_REG_ARM64_X0; i < PERF_REG_ARM64_MAX; ++i) { 74 SetUContextReg(ucontext.uc_mcontext.regs[i], i); 75 } 76#elif defined(__arm__) 77 SetUContextReg(ucontext.uc_mcontext.arm_r0, PERF_REG_ARM_R0); 78 SetUContextReg(ucontext.uc_mcontext.arm_r1, PERF_REG_ARM_R1); 79 SetUContextReg(ucontext.uc_mcontext.arm_r2, PERF_REG_ARM_R2); 80 SetUContextReg(ucontext.uc_mcontext.arm_r3, PERF_REG_ARM_R3); 81 SetUContextReg(ucontext.uc_mcontext.arm_r4, PERF_REG_ARM_R4); 82 SetUContextReg(ucontext.uc_mcontext.arm_r5, PERF_REG_ARM_R5); 83 SetUContextReg(ucontext.uc_mcontext.arm_r6, PERF_REG_ARM_R6); 84 SetUContextReg(ucontext.uc_mcontext.arm_r7, PERF_REG_ARM_R7); 85 SetUContextReg(ucontext.uc_mcontext.arm_r8, PERF_REG_ARM_R8); 86 SetUContextReg(ucontext.uc_mcontext.arm_r9, PERF_REG_ARM_R9); 87 SetUContextReg(ucontext.uc_mcontext.arm_r10, PERF_REG_ARM_R10); 88 SetUContextReg(ucontext.uc_mcontext.arm_fp, PERF_REG_ARM_FP); 89 SetUContextReg(ucontext.uc_mcontext.arm_ip, PERF_REG_ARM_IP); 90 SetUContextReg(ucontext.uc_mcontext.arm_sp, PERF_REG_ARM_SP); 91 SetUContextReg(ucontext.uc_mcontext.arm_lr, PERF_REG_ARM_LR); 92 SetUContextReg(ucontext.uc_mcontext.arm_pc, PERF_REG_ARM_PC); 93#endif 94 return ucontext; 95} 96 97std::vector<uint64_t> UnwindCallChain(int abi, const ThreadEntry& thread, 98 const RegSet& regs, const char* stack, 99 size_t stack_size, bool strict_arch_check) { 100 std::vector<uint64_t> result; 101 ArchType arch = (abi != PERF_SAMPLE_REGS_ABI_32) ? 102 ScopedCurrentArch::GetCurrentArch() : 103 ScopedCurrentArch::GetCurrentArch32(); 104 if (!IsArchTheSame(arch, GetBuildArch(), strict_arch_check)) { 105 LOG(FATAL) << "simpleperf is built in arch " << GetArchString(GetBuildArch()) 106 << ", and can't do stack unwinding for arch " << GetArchString(arch); 107 return result; 108 } 109 uint64_t sp_reg_value; 110 if (!GetSpRegValue(regs, arch, &sp_reg_value)) { 111 LOG(ERROR) << "can't get sp reg value"; 112 return result; 113 } 114 uint64_t stack_addr = sp_reg_value; 115 116 std::vector<backtrace_map_t> bt_maps(thread.maps->size()); 117 size_t map_index = 0; 118 for (auto& map : *thread.maps) { 119 backtrace_map_t& bt_map = bt_maps[map_index++]; 120 bt_map.start = map->start_addr; 121 bt_map.end = map->start_addr + map->len; 122 bt_map.offset = map->pgoff; 123 bt_map.name = map->dso->GetDebugFilePath(); 124 } 125 std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(thread.pid, bt_maps)); 126 127 backtrace_stackinfo_t stack_info; 128 stack_info.start = stack_addr; 129 stack_info.end = stack_addr + stack_size; 130 stack_info.data = reinterpret_cast<const uint8_t*>(stack); 131 132 std::unique_ptr<Backtrace> backtrace( 133 Backtrace::CreateOffline(thread.pid, thread.tid, backtrace_map.get(), stack_info, true)); 134 ucontext_t ucontext = BuildUContextFromRegs(regs); 135 if (backtrace->Unwind(0, &ucontext)) { 136 for (auto it = backtrace->begin(); it != backtrace->end(); ++it) { 137 // Unwinding in arm architecture can return 0 pc address. 138 if (it->pc == 0) { 139 break; 140 } 141 result.push_back(it->pc); 142 } 143 } 144 return result; 145} 146