1 /*
2  * Copyright (c) 2021-2023 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(__aarch64__)
17 #include "dfx_regs.h"
18 
19 #include <elf.h>
20 #include <securec.h>
21 #include <stdint.h>
22 #include <sys/ptrace.h>
23 #include <sys/uio.h>
24 #include "dfx_define.h"
25 #include "dfx_log.h"
26 #include "dfx_elf.h"
27 #include "string_printf.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
SetFromUcontext(const ucontext_t & context)31 void DfxRegsArm64::SetFromUcontext(const ucontext_t &context)
32 {
33     if (regsData_.size() < REG_LAST) {
34         return;
35     }
36     regsData_[REG_AARCH64_X0] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X0]);
37     regsData_[REG_AARCH64_X1] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X1]);
38     regsData_[REG_AARCH64_X2] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X2]);
39     regsData_[REG_AARCH64_X3] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X3]);
40     regsData_[REG_AARCH64_X4] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X4]);
41     regsData_[REG_AARCH64_X5] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X5]);
42     regsData_[REG_AARCH64_X6] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X6]);
43     regsData_[REG_AARCH64_X7] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X7]);
44     regsData_[REG_AARCH64_X8] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X8]);
45     regsData_[REG_AARCH64_X9] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X9]);
46     regsData_[REG_AARCH64_X10] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X10]);
47     regsData_[REG_AARCH64_X11] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X11]);
48     regsData_[REG_AARCH64_X12] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X12]);
49     regsData_[REG_AARCH64_X13] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X13]);
50     regsData_[REG_AARCH64_X14] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X14]);
51     regsData_[REG_AARCH64_X15] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X15]);
52     regsData_[REG_AARCH64_X16] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X16]);
53     regsData_[REG_AARCH64_X17] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X17]);
54     regsData_[REG_AARCH64_X18] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X18]);
55     regsData_[REG_AARCH64_X19] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X19]);
56     regsData_[REG_AARCH64_X20] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X20]);
57     regsData_[REG_AARCH64_X21] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X21]);
58     regsData_[REG_AARCH64_X22] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X22]);
59     regsData_[REG_AARCH64_X23] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X23]);
60     regsData_[REG_AARCH64_X24] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X24]);
61     regsData_[REG_AARCH64_X25] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X25]);
62     regsData_[REG_AARCH64_X26] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X26]);
63     regsData_[REG_AARCH64_X27] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X27]);
64     regsData_[REG_AARCH64_X28] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X28]);
65     regsData_[REG_AARCH64_X29] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X29]);
66     regsData_[REG_AARCH64_X30] = static_cast<uintptr_t>(context.uc_mcontext.regs[REG_AARCH64_X30]);
67     regsData_[REG_AARCH64_X31] = static_cast<uintptr_t>(context.uc_mcontext.sp);
68     regsData_[REG_AARCH64_PC] = static_cast<uintptr_t>(context.uc_mcontext.pc);
69 }
70 
SetFromFpMiniRegs(const uintptr_t * regs,const size_t size)71 void DfxRegsArm64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
72 {
73     if (size < FP_MINI_REGS_SIZE) {
74         return;
75     }
76     regsData_[REG_FP] = regs[0]; // 0 : fp offset
77     regsData_[REG_LR] = regs[1]; // 1 : lr offset
78     regsData_[REG_SP] = regs[2]; // 2 : sp offset
79     regsData_[REG_PC] = regs[3]; // 3 : pc offset
80 }
81 
SetFromQutMiniRegs(const uintptr_t * regs,const size_t size)82 void DfxRegsArm64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
83 {
84     if (size < QUT_MINI_REGS_SIZE) {
85         return;
86     }
87     regsData_[REG_AARCH64_X20] = regs[1]; // 1 : X20 offset
88     regsData_[REG_AARCH64_X28] = regs[2]; // 2 : X28 offset
89     regsData_[REG_FP] = regs[3]; // 3 : fp offset
90     regsData_[REG_SP] = regs[4];  // 4 : sp offset
91     regsData_[REG_PC] = regs[5];  // 5 : pc offset
92     regsData_[REG_LR] = regs[6];  // 6 : lr offset
93 }
94 
SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)95 bool DfxRegsArm64::SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)
96 {
97     uintptr_t lr = regsData_[REG_LR];
98     if (regsData_[REG_PC] == lr) {
99         return false;
100     }
101     regsData_[REG_PC] = lr;
102     return true;
103 }
104 
PrintRegs() const105 std::string DfxRegsArm64::PrintRegs() const
106 {
107     char buf[REGS_PRINT_LEN] = {0};
108     auto regs = GetRegsData();
109 
110     BufferPrintf(buf, sizeof(buf), "x0:%016lx x1:%016lx x2:%016lx x3:%016lx\n", \
111         regs[REG_AARCH64_X0], regs[REG_AARCH64_X1], regs[REG_AARCH64_X2], regs[REG_AARCH64_X3]);
112 
113     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x4:%016lx x5:%016lx x6:%016lx x7:%016lx\n", \
114         regs[REG_AARCH64_X4], regs[REG_AARCH64_X5], regs[REG_AARCH64_X6], regs[REG_AARCH64_X7]);
115 
116     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x8:%016lx x9:%016lx x10:%016lx x11:%016lx\n", \
117         regs[REG_AARCH64_X8], regs[REG_AARCH64_X9], regs[REG_AARCH64_X10], regs[REG_AARCH64_X11]);
118 
119     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x12:%016lx x13:%016lx x14:%016lx x15:%016lx\n", \
120         regs[REG_AARCH64_X12], regs[REG_AARCH64_X13], regs[REG_AARCH64_X14], regs[REG_AARCH64_X15]);
121 
122     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x16:%016lx x17:%016lx x18:%016lx x19:%016lx\n", \
123         regs[REG_AARCH64_X16], regs[REG_AARCH64_X17], regs[REG_AARCH64_X18], regs[REG_AARCH64_X19]);
124 
125     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x20:%016lx x21:%016lx x22:%016lx x23:%016lx\n", \
126         regs[REG_AARCH64_X20], regs[REG_AARCH64_X21], regs[REG_AARCH64_X22], regs[REG_AARCH64_X23]);
127 
128     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x24:%016lx x25:%016lx x26:%016lx x27:%016lx\n", \
129         regs[REG_AARCH64_X24], regs[REG_AARCH64_X25], regs[REG_AARCH64_X26], regs[REG_AARCH64_X27]);
130 
131     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "x28:%016lx x29:%016lx\n", \
132         regs[REG_AARCH64_X28], regs[REG_AARCH64_X29]);
133 
134     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "lr:%016lx sp:%016lx pc:%016lx\n", \
135         regs[REG_AARCH64_X30], regs[REG_SP], regs[REG_PC]);
136 
137     std::string regString = StringPrintf("Registers:\n%s", buf);
138     return regString;
139 }
140 
StepIfSignalFrame(uintptr_t pc,std::shared_ptr<DfxMemory> memory)141 bool DfxRegsArm64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
142 {
143     if (memory == nullptr) {
144         return false;
145     }
146     uint64_t data;
147     if (!memory->ReadU64(pc, &data, false)) {
148         return false;
149     }
150     LOGU("data: %lx", data);
151 
152     // Look for the kernel sigreturn function.
153     // __kernel_rt_sigreturn:
154     // 0xd2801168     mov x8, #0x8b
155     // 0xd4000001     svc #0x0
156     if (data != 0xd4000001d2801168ULL) {
157         return false;
158     }
159 
160     // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
161     uintptr_t scAddr = regsData_[REG_SP] + sizeof(siginfo_t) + 0xb0 + 0x08;
162     LOGU("scAddr: %lx", scAddr);
163     memory->Read(scAddr, regsData_.data(), sizeof(uint64_t) * REG_LAST, false);
164     return true;
165 }
166 } // namespace HiviewDFX
167 } // namespace OHOS
168 #endif
169