1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #if defined(__x86_64__)
17 #include "dfx_regs.h"
18
19 #include <elf.h>
20 #include <securec.h>
21 #include <cstdint>
22 #include <sys/ptrace.h>
23 #include <sys/uio.h>
24
25 #include "dfx_define.h"
26 #include "dfx_log.h"
27 #include "string_printf.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
SetFromUcontext(const ucontext_t & context)31 void DfxRegsX86_64::SetFromUcontext(const ucontext_t &context)
32 {
33 if (regsData_.size() < REG_LAST) {
34 return;
35 }
36 regsData_[REG_X86_64_RAX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RAX]);
37 regsData_[REG_X86_64_RDX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDX]);
38 regsData_[REG_X86_64_RCX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RCX]);
39 regsData_[REG_X86_64_RBX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBX]);
40 regsData_[REG_X86_64_RSI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSI]);
41 regsData_[REG_X86_64_RDI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDI]);
42 regsData_[REG_X86_64_RBP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBP]);
43 regsData_[REG_X86_64_RSP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSP]);
44 regsData_[REG_X86_64_R8] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R8]);
45 regsData_[REG_X86_64_R9] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R9]);
46 regsData_[REG_X86_64_R10] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R10]);
47 regsData_[REG_X86_64_R11] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R11]);
48 regsData_[REG_X86_64_R12] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R12]);
49 regsData_[REG_X86_64_R13] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R13]);
50 regsData_[REG_X86_64_R14] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R14]);
51 regsData_[REG_X86_64_R15] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R15]);
52 regsData_[REG_X86_64_RIP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RIP]);
53 }
54
SetFromFpMiniRegs(const uintptr_t * regs,const size_t size)55 void DfxRegsX86_64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
56 {
57 }
58
SetFromQutMiniRegs(const uintptr_t * regs,const size_t size)59 void DfxRegsX86_64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
60 {
61 }
62
SetPcFromReturnAddress(std::shared_ptr<DfxMemory> memory)63 bool DfxRegsX86_64::SetPcFromReturnAddress(std::shared_ptr<DfxMemory> memory)
64 {
65 uintptr_t newPc;
66 if (!memory->Read<uintptr_t>(regsData_[REG_SP], &newPc, false) ||
67 newPc == regsData_[REG_PC]) {
68 return false;
69 }
70 regsData_[REG_PC] = newPc;
71 return true;
72 }
73
PrintRegs() const74 std::string DfxRegsX86_64::PrintRegs() const
75 {
76 char buf[REGS_PRINT_LEN] = {0};
77 auto regs = GetRegsData();
78
79 BufferPrintf(buf, sizeof(buf), " rax:%016lx rdx:%016lx rcx:%016lx rbx:%016lx\n", \
80 regs[REG_X86_64_RAX], regs[REG_X86_64_RDX], regs[REG_X86_64_RCX], regs[REG_X86_64_RBX]);
81
82 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " rsi:%016lx rdi:%016lx rbp:%016lx rsp:%016lx\n", \
83 regs[REG_X86_64_RSI], regs[REG_X86_64_RDI], regs[REG_X86_64_RBP], regs[REG_X86_64_RSP]);
84
85 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " r8:%016lx r9:%016lx r10:%016lx r11:%016lx\n", \
86 regs[REG_X86_64_R8], regs[REG_X86_64_R9], regs[REG_X86_64_R10], regs[REG_X86_64_R11]);
87
88 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), \
89 " r12:%016lx r13:%016lx r14:%016lx r15:%016lx rip:%016lx\n", \
90 regs[REG_X86_64_R12], regs[REG_X86_64_R13], regs[REG_X86_64_R14], regs[REG_X86_64_R15], regs[REG_X86_64_RIP]);
91
92 std::string regString = StringPrintf("Registers:\n%s", buf);
93 return regString;
94 }
95
StepIfSignalFrame(uintptr_t pc,std::shared_ptr<DfxMemory> memory)96 bool DfxRegsX86_64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
97 {
98 uint64_t data;
99 if (!memory->Read<uint64_t>(pc, &data, false)) {
100 return false;
101 }
102 DFXLOGU("[%{public}d]: data: %{public}" PRIu64 "", __LINE__, data);
103
104 // __restore_rt:
105 // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
106 // 0x0f 0x05 syscall
107 // 0x0f nopl 0x0($rax)
108 if (data != 0x0f0000000fc0c748) {
109 return false;
110 }
111
112 uint16_t data2;
113 pc += sizeof(uint64_t);
114 if (!memory->Read<uint16_t>(pc, &data2, false) || (data2 != 0x0f05)) {
115 DFXLOGU("data2: %{public}x", data2);
116 return false;
117 }
118
119 // Read the mcontext data from the stack.
120 // sp points to the ucontext data structure, read only the mcontext part.
121 ucontext_t ucontext;
122 uintptr_t scAddr = regsData_[REG_SP] + 0x28;
123 DFXLOGU("[%{public}d]: scAddr: %{public}" PRIu64 "", __LINE__, scAddr);
124 memory->Read(scAddr, &ucontext.uc_mcontext, sizeof(ucontext.uc_mcontext), false);
125 SetFromUcontext(ucontext);
126 return true;
127 }
128 } // namespace HiviewDFX
129 } // namespace OHOS
130 #endif
131