• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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