]> sourceware.org Git - systemtap.git/blame - tapset/arm/registers.stp
PR10977: new address size tapset functions
[systemtap.git] / tapset / arm / registers.stp
CommitLineData
5a24160a
WC
1/* Dwarfless register access for arm */
2
029130b7
DS
3%{
4// These functions are largely lifted from arch/arm/kernel/ptrace.c.
5
6static inline unsigned long _stp_kernel_stack_pointer(struct pt_regs *regs)
7{
8 return regs->ARM_sp;
9}
10
11/*
12 * _stp_regs_within_kernel_stack() - check the address in the stack
13 * @regs: pt_regs which contains kernel stack pointer.
14 * @addr: address which is checked.
15 *
16 * _stp_regs_within_kernel_stack() checks @addr is within the kernel
17 * stack page(s). If @addr is within the kernel stack, it returns
18 * true. If not, returns false.
19 */
20bool _stp_regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
21{
22 return ((addr & ~(THREAD_SIZE - 1)) ==
23 (_stp_kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
24}
25
26/*
27 * _stp_regs_get_kernel_stack_nth_addr() - get address of the Nth entry of the stack
28 * @regs: pt_regs which contains kernel stack pointer.
29 * @n: stack entry number.
30 *
31 * _stp_regs_get_kernel_stack_nth_addr() returns the address of the @n
32 * th entry of the kernel stack which is specified by @regs. If the @n
33 * th entry is NOT in the kernel stack, this returns 0.
34 */
35long *
36_stp_regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n)
37{
38 long *addr = (unsigned long *)_stp_kernel_stack_pointer(regs);
39 addr += n;
40 if (_stp_regs_within_kernel_stack(regs, (unsigned long)addr))
41 return addr;
42 else
43 return 0;
44}
45%}
46
6ae3ec1c 47global _reg_offsets[30]
5a24160a 48
6ae3ec1c 49probe init {
5a24160a
WC
50
51 /* Same order as pt_regs */
52 _reg_offsets["r0"] = 0 _reg_offsets["a1"] = 0
53 _reg_offsets["r1"] = 4 _reg_offsets["a2"] = 4
54 _reg_offsets["r2"] = 8 _reg_offsets["a3"] = 8
55 _reg_offsets["r3"] = 12 _reg_offsets["a4"] = 12
56 _reg_offsets["r4"] = 16 _reg_offsets["v1"] = 16
57 _reg_offsets["r5"] = 20 _reg_offsets["v2"] = 20
58 _reg_offsets["r6"] = 24 _reg_offsets["v3"] = 24
59 _reg_offsets["r7"] = 28 _reg_offsets["v4"] = 28
60 _reg_offsets["r8"] = 32 _reg_offsets["v5"] = 32
61 _reg_offsets["r9"] = 36 _reg_offsets["v6"] = 36
62 _reg_offsets["r10"] = 40 _reg_offsets["v7"] = 40
63 _reg_offsets["fp"] = 44 _reg_offsets["v8"] = 44
64 _reg_offsets["ip"] = 48
65 _reg_offsets["sp"] = 52
66 _reg_offsets["lr"] = 56
67 _reg_offsets["pc"] = 60
68 _reg_offsets["cpsr"] = 64
69 _reg_offsets["orig_r0"] = 68
5a24160a
WC
70}
71
72function _stp_get_register_by_offset:long (offset:long) %{ /* pure */
73 long value;
d9aed31e 74 struct pt_regs *regs;
e04b5d74 75 if (CONTEXT->user_mode_p) {
d9aed31e 76 regs = CONTEXT->uregs;
6c40239d
MW
77 } else {
78 regs = CONTEXT->kregs;
d9aed31e
MW
79 }
80 if (!regs) {
5a24160a
WC
81 CONTEXT->last_error = "No registers available in this context";
82 return;
83 }
b7b482fb 84 if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) {
5a24160a 85 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
b7b482fb 86 "Bad register offset: %lld", STAP_ARG_offset);
5a24160a
WC
87 CONTEXT->last_error = CONTEXT->error_buffer;
88 return;
89 }
b7b482fb
SM
90 memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value));
91 STAP_RETVALUE = value;
5a24160a
WC
92%}
93
92c25572
MW
94function _stp_probing_kernel:long () {
95 return !user_mode();
96}
5a24160a 97
93f70a9a
FL
98function arch_bytes:long() %{ /* pure */
99 STAP_RETVALUE = sizeof(long);
100%}
101
102function uarch_bytes:long() {
103 if (!user_mode()) {
104 error("requires user mode")
105 return 0
106 } else
107 return 4
108}
109
5a24160a
WC
110/* Return the named register value as a signed value. */
111function register:long (name:string) {
112 if (!registers_valid()) {
113 error("cannot access CPU registers in this context")
114 return 0
115 }
5a24160a
WC
116 offset = _reg_offsets[name]
117 if (offset == 0 && !(name in _reg_offsets)) {
118 error("Unknown register: " . name)
119 return 0
120 }
121 return _stp_get_register_by_offset(offset)
122}
123
124/*
125 * Return the named register value as an unsigned value. Specifically,
126 * don't sign-extend the register value when promoting it to 64 bits.
127 */
128function u_register:long (name:string) {
129 return register(name) & 0xffffffff;
130}
131
029130b7
DS
132function _stp_get_stack_nth:long (n:long)
133%{ /* pure */
134 unsigned int n = (unsigned int)STAP_ARG_n;
135 struct pt_regs *regs;
136 long *addr;
137
138 STAP_RETVALUE = 0;
139 if (CONTEXT->user_mode_p) {
140 // This function only handles kernel arguments off the stack.
141 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
142 "cannot access function args in this context");
143 CONTEXT->last_error = CONTEXT->error_buffer;
144 return;
145 }
146 regs = CONTEXT->kregs;
147 if (!regs) {
148 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
149 "cannot access function args in this context");
150 CONTEXT->last_error = CONTEXT->error_buffer;
151 return;
152 }
153
154 /* Get the address of the nth item on the stack. */
155 addr = _stp_regs_get_kernel_stack_nth_addr(regs, n);
156 if (addr == NULL) {
157 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
158 "cannot access stack arg(%d)", n);
159 CONTEXT->last_error = CONTEXT->error_buffer;
160 return;
161 }
162 STAP_RETVALUE = kread(addr);
163 return;
164
165 if (0) {
166deref_fault: /* branched to from kread() */
167 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
168 "kernel fault at %#lx accessing stack arg(%d)",
169 (unsigned long)addr, n);
170 CONTEXT->last_error = CONTEXT->error_buffer;
171 }
172%}
173
174
5a24160a
WC
175/* Return the value of function arg #argnum (1=first arg) as a signed value.
176 *
177 * We don't yet support extracting arg #5 and beyond, which are passed
178 * on stack
179 */
180function _stp_arg:long (argnum:long) {
181 val = 0
1482dd61 182 if (argnum < 1 || argnum > 7) {
5a24160a
WC
183 error(sprintf("Cannot access arg(%d)", argnum))
184 return 0
185 }
186
187 if (argnum == 1)
f52d32a9 188 val = register("r0")
5a24160a 189 else if (argnum == 2)
f52d32a9 190 val = register("r1")
5a24160a 191 else if (argnum == 3)
f52d32a9 192 val = register("r2")
5a24160a 193 else if (argnum == 4)
f52d32a9 194 val = register("r3")
029130b7
DS
195 else
196 val = _stp_get_stack_nth(argnum - 5)
5a24160a
WC
197
198 return val;
199}
200
201/* Return the value of function arg #argnum as a signed int. */
202function int_arg:long (argnum:long) {
203 return _stp_arg(argnum)
204}
205
206/* Return the value of function arg #argnum as an unsigned int. */
207function uint_arg:long (argnum:long) {
208 return _stp_arg(argnum) & 0xffffffff;
209}
210
211function long_arg:long (argnum:long) {
212 return int_arg(argnum)
213}
214
215function ulong_arg:long (argnum:long) {
216 return uint_arg(argnum)
217}
218
219function longlong_arg:long (argnum:long) {
220 /*
029130b7
DS
221 * gcc has a few odd rules:
222 * 1) If argnum == 2, the 64-bit arg will start with arg 3.
223 * 2) If argnum == nr_regarg (4), gcc puts the whole 64-bit
224 * arg on the stack.
225 *
226 * Note that following argument numbers will need to be
227 * adjusted.
5a24160a 228 */
029130b7
DS
229 if (argnum == 2 || argnum == 4)
230 argnum++
5a24160a
WC
231 lowbits = uint_arg(argnum)
232 highbits = uint_arg(argnum+1)
233 return ((highbits << 32) | lowbits)
234}
235
236function ulonglong_arg:long (argnum:long) {
237 return longlong_arg(argnum)
238}
239
240function pointer_arg:long (argnum:long) {
241 return ulong_arg(argnum)
242}
243
244function s32_arg:long (argnum:long) {
245 return int_arg(argnum)
246}
247
248function u32_arg:long (argnum:long) {
249 return uint_arg(argnum)
250}
251
252function s64_arg:long (argnum:long) {
253 return longlong_arg(argnum)
254}
255
256function u64_arg:long (argnum:long) {
257 return ulonglong_arg(argnum)
258}
259
260function asmlinkage() %{ /* pure */ %}
261
262function fastcall() %{ /* pure */ %}
263
309d67d8 264function regparm(n:long) %{
5a24160a
WC
265 snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
266 "regparm is invalid on arm.");
267 CONTEXT->last_error = CONTEXT->error_buffer;
268%}
This page took 0.110083 seconds and 5 git commands to generate.