• 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 <securec.h>
20 #include <stdint.h>
21 #include <sys/ptrace.h>
22 #include <sys/uio.h>
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "string_printf.h"
26 
27 namespace OHOS {
28 namespace HiviewDFX {
SetFromUcontext(const ucontext_t & context)29 void DfxRegsLoongArch64::SetFromUcontext(const ucontext_t &context)
30 {
31     if (regsData_.size() < REG_LAST) {
32         return;
33     }
34     for (uint16_t index = REG_LOONGARCH64_R0; index <= REG_LOONGARCH64_R31; index++) {
35         regsData_[index] = static_cast<uintptr_t>(context.uc_mcontext.__gregs[index]);
36     }
37     regsData_[REG_LOONGARCH64_PC] = (static_cast<uintptr_t>(context.uc_mcontext.__pc)); // 32:pc
38 }
39 
SetFromFpMiniRegs(const uintptr_t * regs,const size_t size)40 void DfxRegsLoongArch64::SetFromFpMiniRegs(const uintptr_t* regs, const size_t size)
41 {
42     if (size < FP_MINI_REGS_SIZE) {
43         return;
44     }
45     regsData_[REG_FP] = regs[0]; // 0 : fp offset
46     regsData_[REG_LR] = regs[1]; // 1 : lr offset
47     regsData_[REG_SP] = regs[2]; // 2 : sp offset
48     regsData_[REG_PC] = regs[3]; // 3 : pc offset
49 }
50 
SetFromQutMiniRegs(const uintptr_t * regs,const size_t size)51 void DfxRegsLoongArch64::SetFromQutMiniRegs(const uintptr_t* regs, const size_t size)
52 {
53     if (size < QUT_MINI_REGS_SIZE) {
54         return;
55     }
56 
57     regsData_[REG_FP] = regs[3]; // 3 : fp offset
58     regsData_[REG_SP] = regs[4];  // 4 : sp offset
59     regsData_[REG_PC] = regs[5];  // 5 : pc offset
60     regsData_[REG_LR] = regs[6];  // 6 : lr offset
61 }
62 
SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)63 bool DfxRegsLoongArch64::SetPcFromReturnAddress(MAYBE_UNUSED std::shared_ptr<DfxMemory> memory)
64 {
65     uintptr_t lr = regsData_[REG_LR];
66     if (regsData_[REG_PC] == lr) {
67         return false;
68     }
69     regsData_[REG_PC] = lr;
70     return true;
71 }
72 
PrintRegs() const73 std::string DfxRegsLoongArch64::PrintRegs() const
74 {
75     char buf[REGS_PRINT_LEN] = {0};
76     std::vector<uintptr_t> regs = GetRegsData();
77 
78     BufferPrintf(buf, sizeof(buf), "r0:%016lx r1:%016lx r2:%016lx r3:%016lx\n", \
79         regs[REG_LOONGARCH64_R0], regs[REG_LOONGARCH64_R1], regs[REG_LOONGARCH64_R2], regs[REG_LOONGARCH64_R3]);
80 
81     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r4:%016lx r5:%016lx r6:%016lx r7:%016lx\n", \
82         regs[REG_LOONGARCH64_R4], regs[REG_LOONGARCH64_R5], regs[REG_LOONGARCH64_R6], regs[REG_LOONGARCH64_R7]);
83 
84     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r8:%016lx r9:%016lx r10:%016lx r11:%016lx\n", \
85         regs[REG_LOONGARCH64_R8], regs[REG_LOONGARCH64_R9], regs[REG_LOONGARCH64_R10], regs[REG_LOONGARCH64_R11]);
86 
87     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r12:%016lx r13:%016lx r14:%016lx r15:%016lx\n", \
88         regs[REG_LOONGARCH64_R12], regs[REG_LOONGARCH64_R13], regs[REG_LOONGARCH64_R14], regs[REG_LOONGARCH64_R15]);
89 
90     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r16:%016lx r17:%016lx r18:%016lx r19:%016lx\n", \
91         regs[REG_LOONGARCH64_R16], regs[REG_LOONGARCH64_R17], regs[REG_LOONGARCH64_R18], regs[REG_LOONGARCH64_R19]);
92 
93     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r20:%016lx r21:%016lx x22:%016lx r23:%016lx\n", \
94         regs[REG_LOONGARCH64_R20], regs[REG_LOONGARCH64_R21], regs[REG_LOONGARCH64_R22], regs[REG_LOONGARCH64_R23]);
95 
96     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r24:%016lx r25:%016lx r26:%016lx r27:%016lx\n", \
97         regs[REG_LOONGARCH64_R24], regs[REG_LOONGARCH64_R25], regs[REG_LOONGARCH64_R26], regs[REG_LOONGARCH64_R27]);
98 
99     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "r28:%016lx r29:%016lx r30:%016lx r31:%016lx\n", \
100         regs[REG_LOONGARCH64_R28], regs[REG_LOONGARCH64_R29], regs[REG_LOONGARCH64_R30], regs[REG_LOONGARCH64_R31]);
101 
102     BufferPrintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "lr:%016lx sp:%016lx pc:%016lx\n", \
103         regs[REG_LR], regs[REG_SP], regs[REG_PC]);
104 
105     std::string regString = StringPrintf("Registers:\n%s", buf);
106     return regString;
107 }
108 
StepIfSignalFrame(uintptr_t pc,std::shared_ptr<DfxMemory> memory)109 bool DfxRegsLoongArch64::StepIfSignalFrame(uintptr_t pc, std::shared_ptr<DfxMemory> memory)
110 {
111     uint64_t data;
112     if (!memory->Read<uint64_t>(pc, &data, false)) {
113         return false;
114     }
115     DFXLOGU("data: %llx", data);
116 
117     // Look for the kernel sigreturn function.
118     // arch/loongarch/vdso/sigreturn.S:
119     // 0000000000000000 <__vdso_rt_sigreturn>:
120     // 0: 03822c0b        ori     $r11,$r0,0x8b
121     // 4: 002b0000        syscall 0x0
122 
123     if (data != 0x002b000003822c0bULL) {
124         return false;
125     }
126 
127     // SP + sizeof(siginfo_t) + mcontext_gregs offset.
128     uintptr_t scAddr = regsData_[REG_SP] + sizeof(siginfo_t) + 0xb8;
129     DFXLOGU("scAddr: %llx", scAddr);
130     memory->Read(scAddr, regsData_.data(), sizeof(uint64_t) * REG_LAST, false);
131     return true;
132 }
133 } // namespace HiviewDFX
134 } // namespace OHOS
135 #endif
136