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 "dfx_elf.h"
28 #include "string_printf.h"
29
30 namespace OHOS {
31 namespace HiviewDFX {
SetFromUcontext(const ucontext_t & context)32 void DfxRegsX86_64::SetFromUcontext(const ucontext_t &context)
33 {
34 if (regsData_.size() < REG_LAST) {
35 return;
36 }
37 regsData_[REG_X86_64_RAX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RAX]);
38 regsData_[REG_X86_64_RDX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDX]);
39 regsData_[REG_X86_64_RCX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RCX]);
40 regsData_[REG_X86_64_RBX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBX]);
41 regsData_[REG_X86_64_RSI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSI]);
42 regsData_[REG_X86_64_RDI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDI]);
43 regsData_[REG_X86_64_RBP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBP]);
44 regsData_[REG_X86_64_RSP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSP]);
45 regsData_[REG_X86_64_R8] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R8]);
46 regsData_[REG_X86_64_R9] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R9]);
47 regsData_[REG_X86_64_R10] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R10]);
48 regsData_[REG_X86_64_R11] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R11]);
49 regsData_[REG_X86_64_R12] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R12]);
50 regsData_[REG_X86_64_R13] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R13]);
51 regsData_[REG_X86_64_R14] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R14]);
52 regsData_[REG_X86_64_R15] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R15]);
53 regsData_[REG_X86_64_RIP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RIP]);
54 }
55
SetFromFpMiniRegs(const uintptr_t * regs,const size_t size)56 void DfxRegsX86_64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
57 {
58 }
59
SetFromQutMiniRegs(const uintptr_t * regs,const size_t size)60 void DfxRegsX86_64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
61 {
62 }
63
SetPcFromReturnAddress(std::shared_ptr<DfxMemory> memory)64 bool DfxRegsX86_64::SetPcFromReturnAddress(std::shared_ptr<DfxMemory> memory)
65 {
66 uintptr_t newPc;
67 if (!memory->ReadUptr(regsData_[REG_SP], &newPc, false) ||
68 newPc == regsData_[REG_PC]) {
69 return false;
70 }
71 regsData_[REG_PC] = newPc;
72 return true;
73 }
74
PrintRegs() const75 std::string DfxRegsX86_64::PrintRegs() const
76 {
77 char buf[REGS_PRINT_LEN] = {0};
78 auto regs = GetRegsData();
79
80 BufferPrintf(buf, sizeof(buf), " rax:%016lx rdx:%016lx rcx:%016lx rbx:%016lx\n", \
81 regs[REG_X86_64_RAX], regs[REG_X86_64_RDX], regs[REG_X86_64_RCX], regs[REG_X86_64_RBX]);
82
83 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " rsi:%016lx rdi:%016lx rbp:%016lx rsp:%016lx\n", \
84 regs[REG_X86_64_RSI], regs[REG_X86_64_RDI], regs[REG_X86_64_RBP], regs[REG_X86_64_RSP]);
85
86 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " r8:%016lx r9:%016lx r10:%016lx r11:%016lx\n", \
87 regs[REG_X86_64_R8], regs[REG_X86_64_R9], regs[REG_X86_64_R10], regs[REG_X86_64_R11]);
88
89 BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), \
90 " r12:%016lx r13:%016lx r14:%016lx r15:%016lx rip:%016lx\n", \
91 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]);
92
93 std::string regString = StringPrintf("Registers:\n%s", buf);
94 return regString;
95 }
96
StepIfSignalFrame(uintptr_t pc,std::shared_ptr<DfxMemory> memory)97 bool DfxRegsX86_64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
98 {
99 uint64_t data;
100 if (!memory->ReadU64(pc, &data, false)) {
101 return false;
102 }
103 LOGU("data: %llx", data);
104
105 // __restore_rt:
106 // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
107 // 0x0f 0x05 syscall
108 // 0x0f nopl 0x0($rax)
109 if (data != 0x0f0000000fc0c748) {
110 return false;
111 }
112
113 uint16_t data2;
114 pc += sizeof(uint64_t);
115 if (!memory->ReadU16(pc, &data2, false) || (data2 != 0x0f05)) {
116 LOGU("data2: %x", data2);
117 return false;
118 }
119
120 // Read the mcontext data from the stack.
121 // sp points to the ucontext data structure, read only the mcontext part.
122 ucontext_t ucontext;
123 uintptr_t scAddr = regsData_[REG_SP] + 0x28;
124 LOGU("scAddr: %llx", scAddr);
125 memory->Read(scAddr, &ucontext.uc_mcontext, sizeof(ucontext.uc_mcontext), false);
126 SetFromUcontext(ucontext);
127 return true;
128 }
129 } // namespace HiviewDFX
130 } // namespace OHOS
131 #endif
132