1 /*
2 * Copyright (c) 2021-2024 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 #ifndef DFX_REGS_GET_H
16 #define DFX_REGS_GET_H
17
18 #include <cstdint>
19 #include <string>
20 #include <memory>
21 #include <vector>
22
23 #include "dfx_define.h"
24 #include "unwind_define.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28
29 #if defined(__arm__)
30
GetLocalRegs(void * regs)31 inline AT_ALWAYS_INLINE void GetLocalRegs(void* regs)
32 {
33 asm volatile(
34 ".align 2\n"
35 "bx pc\n"
36 "nop\n"
37 ".code 32\n"
38 "stmia %[base], {r0-r12}\n"
39 "add %[base], #52\n"
40 "mov r1, r13\n"
41 "mov r2, r14\n"
42 "mov r3, r15\n"
43 "stmia %[base], {r1-r3}\n"
44 "orr %[base], pc, #1\n"
45 "bx %[base]\n"
46 : [base] "+r"(regs)
47 :
48 : "memory");
49 }
50
51 // Only get 4 registers(r7/r11/sp/pc)
GetFramePointerMiniRegs(void * regs,size_t size)52 inline AT_ALWAYS_INLINE void GetFramePointerMiniRegs(void *regs, size_t size)
53 {
54 if (size < FP_MINI_REGS_SIZE) {
55 return;
56 }
57 asm volatile(
58 ".align 2\n"
59 "bx pc\n"
60 "nop\n"
61 ".code 32\n"
62 "stmia %[base], {r7, r11}\n"
63 "add %[base], #8\n"
64 "mov r1, r13\n"
65 "mov r2, r15\n"
66 "stmia %[base], {r1, r2}\n"
67 "orr %[base], pc, #1\n"
68 "bx %[base]\n"
69 : [base] "+r"(regs)
70 :
71 : "r1", "r2", "memory");
72 }
73
74 // Fill regs[7] with [r4, r7, r10, r11, sp, pc, unset].
GetQuickenMiniRegsAsm(void * regs)75 inline AT_ALWAYS_INLINE void GetQuickenMiniRegsAsm(void *regs)
76 {
77 asm volatile(
78 ".align 2\n"
79 "bx pc\n"
80 "nop\n"
81 ".code 32\n"
82 "stmia %[base], {r4, r7, r10, r11}\n"
83 "add %[base], #16\n"
84 "mov r1, r13\n"
85 "mov r2, r15\n"
86 "stmia %[base], {r1, r2}\n"
87 "orr %[base], pc, #1\n"
88 "bx %[base]\n"
89 : [base] "+r"(regs)
90 :
91 : "r1", "r2", "memory");
92 }
93
94 #elif defined(__aarch64__)
95
96 inline AT_ALWAYS_INLINE void GetLocalRegs(void* regs)
97 {
98 asm volatile(
99 "1:\n"
100 "stp x0, x1, [%[base], #0]\n"
101 "stp x2, x3, [%[base], #16]\n"
102 "stp x4, x5, [%[base], #32]\n"
103 "stp x6, x7, [%[base], #48]\n"
104 "stp x8, x9, [%[base], #64]\n"
105 "stp x10, x11, [%[base], #80]\n"
106 "stp x12, x13, [%[base], #96]\n"
107 "stp x14, x15, [%[base], #112]\n"
108 "stp x16, x17, [%[base], #128]\n"
109 "stp x18, x19, [%[base], #144]\n"
110 "stp x20, x21, [%[base], #160]\n"
111 "stp x22, x23, [%[base], #176]\n"
112 "stp x24, x25, [%[base], #192]\n"
113 "stp x26, x27, [%[base], #208]\n"
114 "stp x28, x29, [%[base], #224]\n"
115 "str x30, [%[base], #240]\n"
116 "mov x12, sp\n"
117 "adr x13, 1b\n"
118 "stp x12, x13, [%[base], #248]\n"
119 : [base] "+r"(regs)
120 :
121 : "x12", "x13", "memory");
122 }
123
124 // Only get 4 registers from x29 to x32.
125 inline AT_ALWAYS_INLINE void GetFramePointerMiniRegs(void *regs, size_t size)
126 {
127 if (size < FP_MINI_REGS_SIZE) {
128 return;
129 }
130 asm volatile(
131 "1:\n"
132 "stp x29, x30, [%[base], #0]\n"
133 "mov x12, sp\n"
134 "adr x13, 1b\n"
135 "stp x12, x13, [%[base], #16]\n"
136 : [base] "+r"(regs)
137 :
138 : "x12", "x13", "memory");
139 }
140
141 // Fill regs[7] with [unuse, unset, x28, x29, sp, pc, unset].
142 inline AT_ALWAYS_INLINE void GetQuickenMiniRegsAsm(void *regs)
143 {
144 asm volatile(
145 "1:\n"
146 "stp x28, x29, [%[base], #16]\n"
147 "mov x12, sp\n"
148 "adr x13, 1b\n"
149 "stp x12, x13, [%[base], #32]\n"
150 : [base] "+r"(regs)
151 :
152 : "x12", "x13", "memory");
153 }
154
155 #elif defined(__x86_64__)
156 extern "C" int _x86_64_getcontext(void* regs);
157 inline AT_ALWAYS_INLINE void GetLocalRegs(void* regs)
158 {
159 _x86_64_getcontext(regs);
160 }
161
162 inline AT_ALWAYS_INLINE void GetFramePointerMiniRegs(void *regs, size_t size)
163 {
164 }
165
166 inline AT_ALWAYS_INLINE void GetQuickenMiniRegsAsm(void *regs)
167 {
168 }
169
170 #elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
171
172 //future work
173 inline AT_ALWAYS_INLINE void GetLocalRegs(void* regs)
174 {
175 }
176
177 inline AT_ALWAYS_INLINE void GetFramePointerMiniRegs(void *regs, size_t size)
178 {
179 }
180
181 inline AT_ALWAYS_INLINE void GetQuickenMiniRegsAsm(void *regs)
182 {
183 }
184
185 #elif defined(__loongarch_lp64)
186
187 inline AT_ALWAYS_INLINE void GetLocalRegs(void* regs)
188 {
189 asm volatile(
190 "st.d $r0, %[base], 0\n"
191 "st.d $r1, %[base], 8\n"
192 "st.d $r2, %[base], 16\n"
193 "st.d $r3, %[base], 24\n"
194 "st.d $r4, %[base], 32\n"
195 "st.d $r5, %[base], 40\n"
196 "st.d $r6, %[base], 48\n"
197 "st.d $r7, %[base], 56\n"
198 "st.d $r8, %[base], 64\n"
199 "st.d $r9, %[base], 72\n"
200 "st.d $r10, %[base], 80\n"
201 "st.d $r11, %[base], 88\n"
202 "st.d $r12, %[base], 96\n"
203 "st.d $r13, %[base], 104\n"
204 "st.d $r14, %[base], 112\n"
205 "st.d $r15, %[base], 120\n"
206 "st.d $r16, %[base], 128\n"
207 "st.d $r17, %[base], 136\n"
208 "st.d $r18, %[base], 144\n"
209 "st.d $r19, %[base], 152\n"
210 "st.d $r20, %[base], 160\n"
211 "st.d $r21, %[base], 168\n"
212 "st.d $r22, %[base], 176\n"
213 "st.d $r23, %[base], 184\n"
214 "st.d $r24, %[base], 192\n"
215 "st.d $r25, %[base], 200\n"
216 "st.d $r26, %[base], 208\n"
217 "st.d $r27, %[base], 216\n"
218 "st.d $r28, %[base], 224\n"
219 "st.d $r29, %[base], 232\n"
220 "st.d $r30, %[base], 240\n"
221 "st.d $r31, %[base], 248\n"
222 "pcaddi $t0, -32\n"
223 "st.d $t0, %[base], 256\n"
224 : [base] "+r"(regs)
225 :
226 : "$t0", "memory");
227 }
228
229 inline AT_ALWAYS_INLINE void GetFramePointerMiniRegs(void *regs)
230 {
231 asm volatile(
232 "st.d $fp, %[base], 0\n"
233 "st.d $ra, %[base], 8\n"
234 "st.d $sp, %[base], 16\n"
235 "pcaddi $t0, -3\n"
236 "st.d $t0, %[base], 24\n"
237 : [base] "+r"(regs)
238 :
239 : "$t0", "memory");
240 }
241
242 inline AT_ALWAYS_INLINE void GetQuickenMiniRegsAsm(void *regs)
243 {
244 asm volatile(
245 "st.d $fp, %[base], 24\n"
246 "st.d $sp, %[base], 32\n"
247 "pcaddi $t0, -2\n"
248 "st.d $t0, %[base], 40\n"
249 "st.d $ra, %[base], 48\n"
250 : [base] "+r"(regs)
251 :
252 : "$t0", "memory");
253 }
254
255 #endif
256 } // namespace HiviewDFX
257 } // namespace OHOS
258 #endif
259