• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BuildUContextFromRegs(const RegSet & regs)34 static 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 
UnwindCallChain(int abi,const ThreadEntry & thread,const RegSet & regs,const char * stack,size_t stack_size,bool strict_arch_check)97 std::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