upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
145
android/system/extras/simpleperf/dwarf_unwind.cpp
Normal file
145
android/system/extras/simpleperf/dwarf_unwind.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "dwarf_unwind.h"
|
||||
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <backtrace/Backtrace.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "thread_tree.h"
|
||||
|
||||
#define SetUContextReg(dst, perf_regno) \
|
||||
do { \
|
||||
uint64_t value; \
|
||||
if (GetRegValue(regs, perf_regno, &value)) { \
|
||||
(dst) = value; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static ucontext_t BuildUContextFromRegs(const RegSet& regs __attribute__((unused))) {
|
||||
ucontext_t ucontext;
|
||||
memset(&ucontext, 0, sizeof(ucontext));
|
||||
#if defined(__i386__)
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_GS], PERF_REG_X86_GS);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_FS], PERF_REG_X86_FS);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_ES], PERF_REG_X86_ES);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_DS], PERF_REG_X86_DS);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EAX], PERF_REG_X86_AX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EBX], PERF_REG_X86_BX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_ECX], PERF_REG_X86_CX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EDX], PERF_REG_X86_DX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_ESI], PERF_REG_X86_SI);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EDI], PERF_REG_X86_DI);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EBP], PERF_REG_X86_BP);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EIP], PERF_REG_X86_IP);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_ESP], PERF_REG_X86_SP);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_CS], PERF_REG_X86_CS);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_EFL], PERF_REG_X86_FLAGS);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_SS], PERF_REG_X86_SS);
|
||||
#elif defined(__x86_64__)
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R8], PERF_REG_X86_R8);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R9], PERF_REG_X86_R9);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R10], PERF_REG_X86_R10);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R11], PERF_REG_X86_R11);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R12], PERF_REG_X86_R12);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R13], PERF_REG_X86_R13);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R14], PERF_REG_X86_R14);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_R15], PERF_REG_X86_R15);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RDI], PERF_REG_X86_DI);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RSI], PERF_REG_X86_SI);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RBP], PERF_REG_X86_BP);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RBX], PERF_REG_X86_BX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RDX], PERF_REG_X86_DX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RAX], PERF_REG_X86_AX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RCX], PERF_REG_X86_CX);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RSP], PERF_REG_X86_SP);
|
||||
SetUContextReg(ucontext.uc_mcontext.gregs[REG_RIP], PERF_REG_X86_IP);
|
||||
#elif defined(__aarch64__)
|
||||
for (size_t i = PERF_REG_ARM64_X0; i < PERF_REG_ARM64_MAX; ++i) {
|
||||
SetUContextReg(ucontext.uc_mcontext.regs[i], i);
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r0, PERF_REG_ARM_R0);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r1, PERF_REG_ARM_R1);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r2, PERF_REG_ARM_R2);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r3, PERF_REG_ARM_R3);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r4, PERF_REG_ARM_R4);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r5, PERF_REG_ARM_R5);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r6, PERF_REG_ARM_R6);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r7, PERF_REG_ARM_R7);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r8, PERF_REG_ARM_R8);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r9, PERF_REG_ARM_R9);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_r10, PERF_REG_ARM_R10);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_fp, PERF_REG_ARM_FP);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_ip, PERF_REG_ARM_IP);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_sp, PERF_REG_ARM_SP);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_lr, PERF_REG_ARM_LR);
|
||||
SetUContextReg(ucontext.uc_mcontext.arm_pc, PERF_REG_ARM_PC);
|
||||
#endif
|
||||
return ucontext;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> UnwindCallChain(int abi, const ThreadEntry& thread,
|
||||
const RegSet& regs, const char* stack,
|
||||
size_t stack_size, bool strict_arch_check) {
|
||||
std::vector<uint64_t> result;
|
||||
ArchType arch = (abi != PERF_SAMPLE_REGS_ABI_32) ?
|
||||
ScopedCurrentArch::GetCurrentArch() :
|
||||
ScopedCurrentArch::GetCurrentArch32();
|
||||
if (!IsArchTheSame(arch, GetBuildArch(), strict_arch_check)) {
|
||||
LOG(FATAL) << "simpleperf is built in arch " << GetArchString(GetBuildArch())
|
||||
<< ", and can't do stack unwinding for arch " << GetArchString(arch);
|
||||
return result;
|
||||
}
|
||||
uint64_t sp_reg_value;
|
||||
if (!GetSpRegValue(regs, arch, &sp_reg_value)) {
|
||||
LOG(ERROR) << "can't get sp reg value";
|
||||
return result;
|
||||
}
|
||||
uint64_t stack_addr = sp_reg_value;
|
||||
|
||||
std::vector<backtrace_map_t> bt_maps(thread.maps->size());
|
||||
size_t map_index = 0;
|
||||
for (auto& map : *thread.maps) {
|
||||
backtrace_map_t& bt_map = bt_maps[map_index++];
|
||||
bt_map.start = map->start_addr;
|
||||
bt_map.end = map->start_addr + map->len;
|
||||
bt_map.offset = map->pgoff;
|
||||
bt_map.name = map->dso->GetDebugFilePath();
|
||||
}
|
||||
std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(thread.pid, bt_maps));
|
||||
|
||||
backtrace_stackinfo_t stack_info;
|
||||
stack_info.start = stack_addr;
|
||||
stack_info.end = stack_addr + stack_size;
|
||||
stack_info.data = reinterpret_cast<const uint8_t*>(stack);
|
||||
|
||||
std::unique_ptr<Backtrace> backtrace(
|
||||
Backtrace::CreateOffline(thread.pid, thread.tid, backtrace_map.get(), stack_info, true));
|
||||
ucontext_t ucontext = BuildUContextFromRegs(regs);
|
||||
if (backtrace->Unwind(0, &ucontext)) {
|
||||
for (auto it = backtrace->begin(); it != backtrace->end(); ++it) {
|
||||
// Unwinding in arm architecture can return 0 pc address.
|
||||
if (it->pc == 0) {
|
||||
break;
|
||||
}
|
||||
result.push_back(it->pc);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue