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