• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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