1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2023 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(__aarch64__)
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#include "dfx_define.h"
25800b99b8Sopenharmony_ci#include "dfx_log.h"
26800b99b8Sopenharmony_ci#include "dfx_elf.h"
27800b99b8Sopenharmony_ci#include "string_printf.h"
28800b99b8Sopenharmony_ci
29800b99b8Sopenharmony_cinamespace OHOS {
30800b99b8Sopenharmony_cinamespace HiviewDFX {
31800b99b8Sopenharmony_civoid DfxRegsArm64::SetFromUcontext(const ucontext_t &context)
32800b99b8Sopenharmony_ci{
33800b99b8Sopenharmony_ci    if (regsData_.size() < REG_LAST) {
34800b99b8Sopenharmony_ci        return;
35800b99b8Sopenharmony_ci    }
36800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X0] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X0]);
37800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X1] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X1]);
38800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X2] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X2]);
39800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X3] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X3]);
40800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X4] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X4]);
41800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X5] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X5]);
42800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X6] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X6]);
43800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X7] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X7]);
44800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X8] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X8]);
45800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X9] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X9]);
46800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X10] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X10]);
47800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X11] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X11]);
48800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X12] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X12]);
49800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X13] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X13]);
50800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X14] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X14]);
51800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X15] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X15]);
52800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X16] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X16]);
53800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X17] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X17]);
54800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X18] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X18]);
55800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X19] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X19]);
56800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X20] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X20]);
57800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X21] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X21]);
58800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X22] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X22]);
59800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X23] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X23]);
60800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X24] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X24]);
61800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X25] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X25]);
62800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X26] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X26]);
63800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X27] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X27]);
64800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X28] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X28]);
65800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X29] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X29]);
66800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X30] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X30]);
67800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_X31] = static_cast<uintptr_t>(context.uc_mcontext.sp);
68800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_PC] = static_cast<uintptr_t>(context.uc_mcontext.pc);
69800b99b8Sopenharmony_ci}
70800b99b8Sopenharmony_ci
71800b99b8Sopenharmony_civoid DfxRegsArm64::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 DfxRegsArm64::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_AARCH64_X20] = regs[1]; // 1 : X20 offset
88800b99b8Sopenharmony_ci    regsData_[REG_AARCH64_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 DfxRegsArm64::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 DfxRegsArm64::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_AARCH64_X0], regs[REG_AARCH64_X1], regs[REG_AARCH64_X2], regs[REG_AARCH64_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_AARCH64_X4], regs[REG_AARCH64_X5], regs[REG_AARCH64_X6], regs[REG_AARCH64_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_AARCH64_X8], regs[REG_AARCH64_X9], regs[REG_AARCH64_X10], regs[REG_AARCH64_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_AARCH64_X12], regs[REG_AARCH64_X13], regs[REG_AARCH64_X14], regs[REG_AARCH64_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_AARCH64_X16], regs[REG_AARCH64_X17], regs[REG_AARCH64_X18], regs[REG_AARCH64_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_AARCH64_X20], regs[REG_AARCH64_X21], regs[REG_AARCH64_X22], regs[REG_AARCH64_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_AARCH64_X24], regs[REG_AARCH64_X25], regs[REG_AARCH64_X26], regs[REG_AARCH64_X27]);
130800b99b8Sopenharmony_ci
131800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x28:%016lx x29:%016lx\n", \
132800b99b8Sopenharmony_ci        regs[REG_AARCH64_X28], regs[REG_AARCH64_X29]);
133800b99b8Sopenharmony_ci
134800b99b8Sopenharmony_ci    BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "lr:%016lx sp:%016lx pc:%016lx\n", \
135800b99b8Sopenharmony_ci        regs[REG_AARCH64_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 DfxRegsArm64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
142800b99b8Sopenharmony_ci{
143800b99b8Sopenharmony_ci    if (memory == nullptr) {
144800b99b8Sopenharmony_ci        return false;
145800b99b8Sopenharmony_ci    }
146800b99b8Sopenharmony_ci    uint64_t data;
147800b99b8Sopenharmony_ci    if (!memory->ReadU64(pc, &data, false)) {
148800b99b8Sopenharmony_ci        return false;
149800b99b8Sopenharmony_ci    }
150800b99b8Sopenharmony_ci    DFXLOGU("data: %{public}lx", data);
151800b99b8Sopenharmony_ci
152800b99b8Sopenharmony_ci    // Look for the kernel sigreturn function.
153800b99b8Sopenharmony_ci    // __kernel_rt_sigreturn:
154800b99b8Sopenharmony_ci    // 0xd2801168     mov x8, #0x8b
155800b99b8Sopenharmony_ci    // 0xd4000001     svc #0x0
156800b99b8Sopenharmony_ci    if (data != 0xd4000001d2801168ULL) {
157800b99b8Sopenharmony_ci        return false;
158800b99b8Sopenharmony_ci    }
159800b99b8Sopenharmony_ci
160800b99b8Sopenharmony_ci    // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
161800b99b8Sopenharmony_ci    uintptr_t scAddr = regsData_[REG_SP] + sizeof(siginfo_t) + 0xb0 + 0x08;
162800b99b8Sopenharmony_ci    DFXLOGU("scAddr: %{public}lx", scAddr);
163800b99b8Sopenharmony_ci    memory->Read(scAddr, regsData_.data(), sizeof(uint64_t) * REG_LAST, false);
164800b99b8Sopenharmony_ci    return true;
165800b99b8Sopenharmony_ci}
166800b99b8Sopenharmony_ci} // namespace HiviewDFX
167800b99b8Sopenharmony_ci} // namespace OHOS
168800b99b8Sopenharmony_ci#endif
169