• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Institute of Software, Chinese Academy of Sciences.
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(__loongarch_lp64)
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 DfxRegsLoongArch64::SetFromUcontext(const ucontext_t &context)
32 {
33     std::vector<uintptr_t> regs;
34     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R0]));   // 0:r0
35     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R1]));   // 1:r1
36     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R2]));   // 2:r2
37     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R3]));   // 3:r3
38     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R4]));   // 4:r4
39     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R5]));   // 5:r5
40     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R6]));   // 6:r6
41     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R7]));   // 7:r7
42     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R8]));   // 8:r8
43     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R9]));   // 9:r9
44     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R10])); // 10:r10
45     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R11])); // 11:r11
46     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R12])); // 12:r12
47     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R13])); // 13:r13
48     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R14])); // 14:r14
49     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R15])); // 15:r15
50     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R16])); // 16:r16
51     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R17])); // 17:r17
52     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R18])); // 18:r18
53     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R19])); // 19:r19
54     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R20])); // 20:r20
55     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R21])); // 21:r21
56     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R22])); // 22:r22
57     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R23])); // 23:r23
58     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R24])); // 24:r24
59     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R25])); // 25:r25
60     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R26])); // 26:r26
61     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R27])); // 27:r27
62     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R28])); // 28:r28
63     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R29])); // 29:r29
64     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R30])); // 30:r30
65     regs.emplace_back(uintptr_t(context.uc_mcontext.__gregs[REG_LOONGARCH64_R31])); // 31:r31
66     regs.emplace_back(uintptr_t(context.uc_mcontext.__pc)); // 32:pc
67 
68     SetRegsData(regs);
69 }
70 
SetFromFpMiniRegs(const uintptr_t * regs,const size_t size)71 void DfxRegsLoongArch64::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 DfxRegsLoongArch64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
83 {
84     if (size < QUT_MINI_REGS_SIZE) {
85         return;
86     }
87 
88     regsData_[REG_FP] = regs[3]; // 3 : fp offset
89     regsData_[REG_SP] = regs[4];  // 4 : sp offset
90     regsData_[REG_PC] = regs[5];  // 5 : pc offset
91     regsData_[REG_LR] = regs[6];  // 6 : lr offset
92 }
93 
SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)94 bool DfxRegsLoongArch64::SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)
95 {
96     uintptr_t lr = regsData_[REG_LR];
97     if (regsData_[REG_PC] == lr) {
98         return false;
99     }
100     regsData_[REG_PC] = lr;
101     return true;
102 }
103 
PrintRegs() const104 std::string DfxRegsLoongArch64::PrintRegs() const
105 {
106     char buf[REGS_PRINT_LEN] = {0};
107     std::vector<uintptr_t> regs = GetRegsData();
108 
109     BufferPrintf(buf, sizeof(buf), "r0:%016lx r1:%016lx r2:%016lx r3:%016lx\n", \
110         regs[REG_LOONGARCH64_R0], regs[REG_LOONGARCH64_R1], regs[REG_LOONGARCH64_R2], regs[REG_LOONGARCH64_R3]);
111 
112     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r4:%016lx r5:%016lx r6:%016lx r7:%016lx\n", \
113         regs[REG_LOONGARCH64_R4], regs[REG_LOONGARCH64_R5], regs[REG_LOONGARCH64_R6], regs[REG_LOONGARCH64_R7]);
114 
115     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r8:%016lx r9:%016lx r10:%016lx r11:%016lx\n", \
116         regs[REG_LOONGARCH64_R8], regs[REG_LOONGARCH64_R9], regs[REG_LOONGARCH64_R10], regs[REG_LOONGARCH64_R11]);
117 
118     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r12:%016lx r13:%016lx r14:%016lx r15:%016lx\n", \
119         regs[REG_LOONGARCH64_R12], regs[REG_LOONGARCH64_R13], regs[REG_LOONGARCH64_R14], regs[REG_LOONGARCH64_R15]);
120 
121     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r16:%016lx r17:%016lx r18:%016lx r19:%016lx\n", \
122         regs[REG_LOONGARCH64_R16], regs[REG_LOONGARCH64_R17], regs[REG_LOONGARCH64_R18], regs[REG_LOONGARCH64_R19]);
123 
124     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r20:%016lx r21:%016lx x22:%016lx r23:%016lx\n", \
125         regs[REG_LOONGARCH64_R20], regs[REG_LOONGARCH64_R21], regs[REG_LOONGARCH64_R22], regs[REG_LOONGARCH64_R23]);
126 
127     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r24:%016lx r25:%016lx r26:%016lx r27:%016lx\n", \
128         regs[REG_LOONGARCH64_R24], regs[REG_LOONGARCH64_R25], regs[REG_LOONGARCH64_R26], regs[REG_LOONGARCH64_R27]);
129 
130     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r28:%016lx r29:%016lx r30:%016lx r31:%016lx\n", \
131         regs[REG_LOONGARCH64_R28], regs[REG_LOONGARCH64_R29], regs[REG_LOONGARCH64_R30], regs[REG_LOONGARCH64_R31]);
132 
133     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "lr:%016lx sp:%016lx pc:%016lx\n", \
134         regs[REG_LR], regs[REG_SP], regs[REG_PC]);
135 
136     std::string regString = StringPrintf("Registers:\n%s", buf);
137     return regString;
138 }
139 
StepIfSignalFrame(uintptr_t pc,std::shared_ptr<DfxMemory> memory)140 bool DfxRegsLoongArch64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
141 {
142     uint64_t data;
143     if (!memory->Read<uint64_t>(pc, &data, false)) {
144         return false;
145     }
146     DFXLOGU("data: %llx", data);
147 
148     // Look for the kernel sigreturn function.
149     // arch/loongarch/vdso/sigreturn.S:
150     // 0000000000000000 <__vdso_rt_sigreturn>:
151     // 0: 03822c0b        ori     $r11,$r0,0x8b
152     // 4: 002b0000        syscall 0x0
153 
154     if (data != 0x002b000003822c0bULL) {
155         return false;
156     }
157 
158     // SP + sizeof(siginfo_t) + mcontext_gregs offset.
159     uintptr_t scAddr = regsData_[REG_SP] + sizeof(siginfo_t) + 0xb8;
160     DFXLOGU("scAddr: %llx", scAddr);
161     memory->Read(scAddr, regsData_.data(), sizeof(uint64_t) * REG_LAST, false);
162     return true;
163 }
164 } // namespace HiviewDFX
165 } // namespace OHOS
166 #endif
167