1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright 2024 Institute of Software, Chinese Academy of Sciences.
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(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
17800b99b8Sopenharmony_ci#include "dfx_regs.h"
18800b99b8Sopenharmony_ci
19800b99b8Sopenharmony_ci#include <elf.h>
20800b99b8Sopenharmony_ci#include <securec.h>
21800b99b8Sopenharmony_ci#include <stdint.h>
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 DfxRegsRiscv64::SetFromUcontext(const ucontext_t &context)
33800b99b8Sopenharmony_ci{
34800b99b8Sopenharmony_ci    if (regsData_.size() < REG_LAST) {
35800b99b8Sopenharmony_ci        return;
36800b99b8Sopenharmony_ci    }
37800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X0] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X0]);
38800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X1] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X1]);
39800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X2] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X2]);
40800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X3] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X3]);
41800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X4] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X4]);
42800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X5] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X5]);
43800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X6] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X6]);
44800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X7] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X7]);
45800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X8] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X8]);
46800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X9] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X9]);
47800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X10] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X10]);
48800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X11] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X11]);
49800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X12] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X12]);
50800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X13] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X13]);
51800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X14] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X14]);
52800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X15] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X15]);
53800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X16] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X16]);
54800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X17] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X17]);
55800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X18] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X18]);
56800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X19] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X19]);
57800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X20] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X20]);
58800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X21] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X21]);
59800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X22] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X22]);
60800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X23] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X23]);
61800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X24] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X24]);
62800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X25] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X25]);
63800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X26] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X26]);
64800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X27] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X27]);
65800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X28] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X28]);
66800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X29] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X29]);
67800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X30] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X30]);
68800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X31] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[REG_RISCV64_X31]);
69800b99b8Sopenharmony_ci}
70800b99b8Sopenharmony_ci
71800b99b8Sopenharmony_civoid DfxRegsRiscv64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
72800b99b8Sopenharmony_ci{
73800b99b8Sopenharmony_ci    if (size < FP_MINI_REGS_SIZE) {
74800b99b8Sopenharmony_ci        return;
75800b99b8Sopenharmony_ci    }
76800b99b8Sopenharmony_ci    regsData_[REG_FP] = regs[0]; // 0 : fp offset
77800b99b8Sopenharmony_ci    regsData_[REG_LR] = regs[1]; // 1 : lr offset
78800b99b8Sopenharmony_ci    regsData_[REG_SP] = regs[2]; // 2 : sp offset
79800b99b8Sopenharmony_ci    regsData_[REG_PC] = regs[3]; // 3 : pc offset
80800b99b8Sopenharmony_ci}
81800b99b8Sopenharmony_ci
82800b99b8Sopenharmony_civoid DfxRegsRiscv64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
83800b99b8Sopenharmony_ci{
84800b99b8Sopenharmony_ci    if (size < QUT_MINI_REGS_SIZE) {
85800b99b8Sopenharmony_ci        return;
86800b99b8Sopenharmony_ci    }
87800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X20] = regs[1]; // 1 : X20 offset
88800b99b8Sopenharmony_ci    regsData_[REG_RISCV64_X28] = regs[2]; // 2 : X28 offset
89800b99b8Sopenharmony_ci    regsData_[REG_FP] = regs[3]; // 3 : fp offset
90800b99b8Sopenharmony_ci    regsData_[REG_SP] = regs[4];  // 4 : sp offset
91800b99b8Sopenharmony_ci    regsData_[REG_PC] = regs[5];  // 5 : pc offset
92800b99b8Sopenharmony_ci    regsData_[REG_LR] = regs[6];  // 6 : lr offset
93800b99b8Sopenharmony_ci}
94800b99b8Sopenharmony_ci
95800b99b8Sopenharmony_cibool DfxRegsRiscv64::SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)
96800b99b8Sopenharmony_ci{
97800b99b8Sopenharmony_ci    uintptr_t lr = regsData_[REG_LR];
98800b99b8Sopenharmony_ci    if (regsData_[REG_PC] == lr) {
99800b99b8Sopenharmony_ci        return false;
100800b99b8Sopenharmony_ci    }
101800b99b8Sopenharmony_ci    regsData_[REG_PC] = lr;
102800b99b8Sopenharmony_ci    return true;
103800b99b8Sopenharmony_ci}
104800b99b8Sopenharmony_ci
105800b99b8Sopenharmony_cistd::string DfxRegsRiscv64::PrintRegs() const
106800b99b8Sopenharmony_ci{
107800b99b8Sopenharmony_ci    char buf[REGS_PRINT_LEN] = {0};
108800b99b8Sopenharmony_ci    auto regs = GetRegsData();
109800b99b8Sopenharmony_ci
110800b99b8Sopenharmony_ci    BufferPrintf(buf, sizeof(buf), "x0:%016lx x1:%016lx x2:%016lx x3:%016lx\n", \
111800b99b8Sopenharmony_ci        regs[REG_RISCV64_X0], regs[REG_RISCV64_X1], regs[REG_RISCV64_X2], regs[REG_RISCV64_X3]);
112800b99b8Sopenharmony_ci
113800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x4:%016lx x5:%016lx x6:%016lx x7:%016lx\n", \
114800b99b8Sopenharmony_ci        regs[REG_RISCV64_X4], regs[REG_RISCV64_X5], regs[REG_RISCV64_X6], regs[REG_RISCV64_X7]);
115800b99b8Sopenharmony_ci
116800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x8:%016lx x9:%016lx x10:%016lx x11:%016lx\n", \
117800b99b8Sopenharmony_ci        regs[REG_RISCV64_X8], regs[REG_RISCV64_X9], regs[REG_RISCV64_X10], regs[REG_RISCV64_X11]);
118800b99b8Sopenharmony_ci
119800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x12:%016lx x13:%016lx x14:%016lx x15:%016lx\n", \
120800b99b8Sopenharmony_ci        regs[REG_RISCV64_X12], regs[REG_RISCV64_X13], regs[REG_RISCV64_X14], regs[REG_RISCV64_X15]);
121800b99b8Sopenharmony_ci
122800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x16:%016lx x17:%016lx x18:%016lx x19:%016lx\n", \
123800b99b8Sopenharmony_ci        regs[REG_RISCV64_X16], regs[REG_RISCV64_X17], regs[REG_RISCV64_X18], regs[REG_RISCV64_X19]);
124800b99b8Sopenharmony_ci
125800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x20:%016lx x21:%016lx x22:%016lx x23:%016lx\n", \
126800b99b8Sopenharmony_ci        regs[REG_RISCV64_X20], regs[REG_RISCV64_X21], regs[REG_RISCV64_X22], regs[REG_RISCV64_X23]);
127800b99b8Sopenharmony_ci
128800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x24:%016lx x25:%016lx x26:%016lx x27:%016lx\n", \
129800b99b8Sopenharmony_ci        regs[REG_RISCV64_X24], regs[REG_RISCV64_X25], regs[REG_RISCV64_X26], regs[REG_RISCV64_X27]);
130800b99b8Sopenharmony_ci
131800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x28:%016lx x29:%016lx\n", \
132800b99b8Sopenharmony_ci        regs[REG_RISCV64_X28], regs[REG_RISCV64_X29]);
133800b99b8Sopenharmony_ci
134800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "lr:%016lx sp:%016lx pc:%016lx\n", \
135800b99b8Sopenharmony_ci        regs[REG_RISCV64_X30], regs[REG_SP], regs[REG_PC]);
136800b99b8Sopenharmony_ci
137800b99b8Sopenharmony_ci    std::string regString = StringPrintf("Registers:\n%s", buf);
138800b99b8Sopenharmony_ci    return regString;
139800b99b8Sopenharmony_ci}
140800b99b8Sopenharmony_ci
141800b99b8Sopenharmony_cibool DfxRegsRiscv64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
142800b99b8Sopenharmony_ci{
143800b99b8Sopenharmony_ci    uint64_t data;
144800b99b8Sopenharmony_ci    if (!memory->ReadU64(pc, &data, false)) {
145800b99b8Sopenharmony_ci        return false;
146800b99b8Sopenharmony_ci    }
147800b99b8Sopenharmony_ci    DFXLOGU("[%{public}d]: data: %{public}llx", __LINE__, data);
148800b99b8Sopenharmony_ci
149800b99b8Sopenharmony_ci    // Look for the kernel sigreturn function.
150800b99b8Sopenharmony_ci    // __kernel_rt_sigreturn:
151800b99b8Sopenharmony_ci    // li a7, __NR_rt_sigreturn
152800b99b8Sopenharmony_ci    // scall
153800b99b8Sopenharmony_ci    const int scallSize = 8;
154800b99b8Sopenharmony_ci    const uint8_t liScall[] = {0x93, 0x08, 0xb0, 0x08, 0x73, 0x00, 0x00, 0x00};
155800b99b8Sopenharmony_ci    if (memcmp(&data, &liScall, scallSize) != 0) {
156800b99b8Sopenharmony_ci        return false;
157800b99b8Sopenharmony_ci    }
158800b99b8Sopenharmony_ci    // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
159800b99b8Sopenharmony_ci    uintptr_t scAddr = regsData_[REG_SP] + sizeof(siginfo_t) + 0xb0 + 0x00;
160800b99b8Sopenharmony_ci    DFXLOGU("[%{public}d]: scAddr: %{public}llx", __LINE__, scAddr);
161800b99b8Sopenharmony_ci    memory->Read(scAddr, regsData_.data(), sizeof(uint64_t) * REG_LAST, false);
162800b99b8Sopenharmony_ci    return true;
163800b99b8Sopenharmony_ci}
164800b99b8Sopenharmony_ci} // namespace HiviewDFX
165800b99b8Sopenharmony_ci} // namespace OHOS
166800b99b8Sopenharmony_ci#endif
167