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 #endif
186 } // namespace HiviewDFX
187 } // namespace OHOS
188 #endif
189