1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#if defined(__x86_64__)
17800b99b8Sopenharmony_ci#include "dfx_regs.h"
18800b99b8Sopenharmony_ci
19800b99b8Sopenharmony_ci#include <elf.h>
20800b99b8Sopenharmony_ci#include <securec.h>
21800b99b8Sopenharmony_ci#include <cstdint>
22800b99b8Sopenharmony_ci#include <sys/ptrace.h>
23800b99b8Sopenharmony_ci#include <sys/uio.h>
24800b99b8Sopenharmony_ci
25800b99b8Sopenharmony_ci#include "dfx_define.h"
26800b99b8Sopenharmony_ci#include "dfx_log.h"
27800b99b8Sopenharmony_ci#include "dfx_elf.h"
28800b99b8Sopenharmony_ci#include "string_printf.h"
29800b99b8Sopenharmony_ci
30800b99b8Sopenharmony_cinamespace OHOS {
31800b99b8Sopenharmony_cinamespace HiviewDFX {
32800b99b8Sopenharmony_civoid DfxRegsX86_64::SetFromUcontext(const ucontext_t &context)
33800b99b8Sopenharmony_ci{
34800b99b8Sopenharmony_ci    if (regsData_.size() < REG_LAST) {
35800b99b8Sopenharmony_ci        return;
36800b99b8Sopenharmony_ci    }
37800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RAX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RAX]);
38800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RDX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDX]);
39800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RCX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RCX]);
40800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RBX] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBX]);
41800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RSI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSI]);
42800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RDI] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RDI]);
43800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RBP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RBP]);
44800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RSP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RSP]);
45800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R8] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R8]);
46800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R9] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R9]);
47800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R10] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R10]);
48800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R11] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R11]);
49800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R12] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R12]);
50800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R13] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R13]);
51800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R14] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R14]);
52800b99b8Sopenharmony_ci    regsData_[REG_X86_64_R15] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_R15]);
53800b99b8Sopenharmony_ci    regsData_[REG_X86_64_RIP] = static_cast<uintptr_t>(context.uc_mcontext.gregs[REG_RIP]);
54800b99b8Sopenharmony_ci}
55800b99b8Sopenharmony_ci
56800b99b8Sopenharmony_civoid DfxRegsX86_64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
57800b99b8Sopenharmony_ci{
58800b99b8Sopenharmony_ci}
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_civoid DfxRegsX86_64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
61800b99b8Sopenharmony_ci{
62800b99b8Sopenharmony_ci}
63800b99b8Sopenharmony_ci
64800b99b8Sopenharmony_cibool DfxRegsX86_64::SetPcFromReturnAddress(std::shared_ptr<DfxMemory> memory)
65800b99b8Sopenharmony_ci{
66800b99b8Sopenharmony_ci    uintptr_t newPc;
67800b99b8Sopenharmony_ci    if (!memory->ReadUptr(regsData_[REG_SP], &newPc, false) ||
68800b99b8Sopenharmony_ci        newPc == regsData_[REG_PC]) {
69800b99b8Sopenharmony_ci        return false;
70800b99b8Sopenharmony_ci    }
71800b99b8Sopenharmony_ci    regsData_[REG_PC] = newPc;
72800b99b8Sopenharmony_ci    return true;
73800b99b8Sopenharmony_ci}
74800b99b8Sopenharmony_ci
75800b99b8Sopenharmony_cistd::string DfxRegsX86_64::PrintRegs() const
76800b99b8Sopenharmony_ci{
77800b99b8Sopenharmony_ci    char buf[REGS_PRINT_LEN] = {0};
78800b99b8Sopenharmony_ci    auto regs = GetRegsData();
79800b99b8Sopenharmony_ci
80800b99b8Sopenharmony_ci    BufferPrintf(buf, sizeof(buf), "  rax:%016lx rdx:%016lx rcx:%016lx rbx:%016lx\n", \
81800b99b8Sopenharmony_ci        regs[REG_X86_64_RAX], regs[REG_X86_64_RDX], regs[REG_X86_64_RCX], regs[REG_X86_64_RBX]);
82800b99b8Sopenharmony_ci
83800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  rsi:%016lx rdi:%016lx rbp:%016lx rsp:%016lx\n", \
84800b99b8Sopenharmony_ci        regs[REG_X86_64_RSI], regs[REG_X86_64_RDI], regs[REG_X86_64_RBP], regs[REG_X86_64_RSP]);
85800b99b8Sopenharmony_ci
86800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "  r8:%016lx r9:%016lx r10:%016lx r11:%016lx\n", \
87800b99b8Sopenharmony_ci        regs[REG_X86_64_R8], regs[REG_X86_64_R9], regs[REG_X86_64_R10], regs[REG_X86_64_R11]);
88800b99b8Sopenharmony_ci
89800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), \
90800b99b8Sopenharmony_ci        "  r12:%016lx r13:%016lx r14:%016lx r15:%016lx rip:%016lx\n", \
91800b99b8Sopenharmony_ci        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]);
92800b99b8Sopenharmony_ci
93800b99b8Sopenharmony_ci    std::string regString = StringPrintf("Registers:\n%s", buf);
94800b99b8Sopenharmony_ci    return regString;
95800b99b8Sopenharmony_ci}
96800b99b8Sopenharmony_ci
97800b99b8Sopenharmony_cibool DfxRegsX86_64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
98800b99b8Sopenharmony_ci{
99800b99b8Sopenharmony_ci    uint64_t data;
100800b99b8Sopenharmony_ci    if (!memory->ReadU64(pc, &data, false)) {
101800b99b8Sopenharmony_ci        return false;
102800b99b8Sopenharmony_ci    }
103800b99b8Sopenharmony_ci    DFXLOGU("[%{public}d]: data: %{public}llx", __LINE__, data);
104800b99b8Sopenharmony_ci
105800b99b8Sopenharmony_ci    // __restore_rt:
106800b99b8Sopenharmony_ci    // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00   mov $0xf,%rax
107800b99b8Sopenharmony_ci    // 0x0f 0x05                            syscall
108800b99b8Sopenharmony_ci    // 0x0f                                 nopl 0x0($rax)
109800b99b8Sopenharmony_ci    if (data != 0x0f0000000fc0c748) {
110800b99b8Sopenharmony_ci        return false;
111800b99b8Sopenharmony_ci    }
112800b99b8Sopenharmony_ci
113800b99b8Sopenharmony_ci    uint16_t data2;
114800b99b8Sopenharmony_ci    pc += sizeof(uint64_t);
115800b99b8Sopenharmony_ci    if (!memory->ReadU16(pc, &data2, false) || (data2 != 0x0f05)) {
116800b99b8Sopenharmony_ci        DFXLOGU("data2: %{public}x", data2);
117800b99b8Sopenharmony_ci        return false;
118800b99b8Sopenharmony_ci    }
119800b99b8Sopenharmony_ci
120800b99b8Sopenharmony_ci    // Read the mcontext data from the stack.
121800b99b8Sopenharmony_ci    // sp points to the ucontext data structure, read only the mcontext part.
122800b99b8Sopenharmony_ci    ucontext_t ucontext;
123800b99b8Sopenharmony_ci    uintptr_t scAddr = regsData_[REG_SP] + 0x28;
124800b99b8Sopenharmony_ci    DFXLOGU("[%{public}d]: scAddr: %{public}llx", __LINE__, scAddr);
125800b99b8Sopenharmony_ci    memory->Read(scAddr, &ucontext.uc_mcontext, sizeof(ucontext.uc_mcontext), false);
126800b99b8Sopenharmony_ci    SetFromUcontext(ucontext);
127800b99b8Sopenharmony_ci    return true;
128800b99b8Sopenharmony_ci}
129800b99b8Sopenharmony_ci} // namespace HiviewDFX
130800b99b8Sopenharmony_ci} // namespace OHOS
131800b99b8Sopenharmony_ci#endif
132