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