| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: fbt_isa.c,v 1.1 2018/05/28 23:47:39 chs Exp $ */ | | 1 | /* $NetBSD: fbt_isa.c,v 1.2 2023/05/22 15:12:54 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * CDDL HEADER START | | 4 | * CDDL HEADER START |
5 | * | | 5 | * |
6 | * The contents of this file are subject to the terms of the | | 6 | * The contents of this file are subject to the terms of the |
7 | * Common Development and Distribution License (the "License"). | | 7 | * Common Development and Distribution License (the "License"). |
8 | * You may not use this file except in compliance with the License. | | 8 | * You may not use this file except in compliance with the License. |
9 | * | | 9 | * |
10 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | | 10 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
11 | * or http://www.opensolaris.org/os/licensing. | | 11 | * or http://www.opensolaris.org/os/licensing. |
12 | * See the License for the specific language governing permissions | | 12 | * See the License for the specific language governing permissions |
13 | * and limitations under the License. | | 13 | * and limitations under the License. |
14 | * | | 14 | * |
| @@ -46,26 +46,46 @@ | | | @@ -46,26 +46,46 @@ |
46 | #include <arm/frame.h> | | 46 | #include <arm/frame.h> |
47 | #include <uvm/uvm_extern.h> | | 47 | #include <uvm/uvm_extern.h> |
48 | | | 48 | |
49 | #include "fbt.h" | | 49 | #include "fbt.h" |
50 | | | 50 | |
51 | #define FBT_PUSHM 0xe92d0000 | | 51 | #define FBT_PUSHM 0xe92d0000 |
52 | #define FBT_POPM 0xe8bd0000 | | 52 | #define FBT_POPM 0xe8bd0000 |
53 | #define FBT_JUMP 0xea000000 | | 53 | #define FBT_JUMP 0xea000000 |
54 | #define FBT_SUBSP 0xe24dd000 | | 54 | #define FBT_SUBSP 0xe24dd000 |
55 | | | 55 | |
56 | #define FBT_ENTRY "entry" | | 56 | #define FBT_ENTRY "entry" |
57 | #define FBT_RETURN "return" | | 57 | #define FBT_RETURN "return" |
58 | | | 58 | |
| | | 59 | static uint32_t |
| | | 60 | ldinstr(const uint32_t *instr) |
| | | 61 | { |
| | | 62 | #ifdef _ARM_ARCH_BE8 /* big-endian data, big-endian instructions */ |
| | | 63 | return *instr; |
| | | 64 | #else /* little-endian instructions */ |
| | | 65 | return le32toh(*instr); |
| | | 66 | #endif |
| | | 67 | } |
| | | 68 | |
| | | 69 | static void |
| | | 70 | stinstr(uint32_t *instr, uint32_t val) |
| | | 71 | { |
| | | 72 | |
| | | 73 | #ifdef _ARM_ARCH_BE8 /* big-endian data, big-endian instructions */ |
| | | 74 | val = bswap32(val); |
| | | 75 | #endif |
| | | 76 | ktext_write(instr, &val, sizeof(val)); /* write little-endian */ |
| | | 77 | } |
| | | 78 | |
59 | int | | 79 | int |
60 | fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval) | | 80 | fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval) |
61 | { | | 81 | { |
62 | solaris_cpu_t *cpu = &solaris_cpu[cpu_number()]; | | 82 | solaris_cpu_t *cpu = &solaris_cpu[cpu_number()]; |
63 | fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)]; | | 83 | fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)]; |
64 | register_t fifthparam; | | 84 | register_t fifthparam; |
65 | | | 85 | |
66 | for (; fbt != NULL; fbt = fbt->fbtp_hashnext) { | | 86 | for (; fbt != NULL; fbt = fbt->fbtp_hashnext) { |
67 | if ((uintptr_t)fbt->fbtp_patchpoint == addr) { | | 87 | if ((uintptr_t)fbt->fbtp_patchpoint == addr) { |
68 | if (fbt->fbtp_roffset == 0) { | | 88 | if (fbt->fbtp_roffset == 0) { |
69 | /* Get 5th parameter from stack */ | | 89 | /* Get 5th parameter from stack */ |
70 | DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); | | 90 | DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
71 | fifthparam = *(register_t *)frame->tf_svc_sp; | | 91 | fifthparam = *(register_t *)frame->tf_svc_sp; |
| @@ -88,93 +108,91 @@ fbt_invop(uintptr_t addr, struct trapfra | | | @@ -88,93 +108,91 @@ fbt_invop(uintptr_t addr, struct trapfra |
88 | } | | 108 | } |
89 | } | | 109 | } |
90 | | | 110 | |
91 | return (0); | | 111 | return (0); |
92 | } | | 112 | } |
93 | | | 113 | |
94 | | | 114 | |
95 | void | | 115 | void |
96 | fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) | | 116 | fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) |
97 | { | | 117 | { |
98 | dtrace_icookie_t c; | | 118 | dtrace_icookie_t c; |
99 | | | 119 | |
100 | c = dtrace_interrupt_disable(); | | 120 | c = dtrace_interrupt_disable(); |
101 | | | 121 | stinstr(fbt->fbtp_patchpoint, val); |
102 | ktext_write(fbt->fbtp_patchpoint, &val, sizeof (val)); | | | |
103 | | | | |
104 | dtrace_interrupt_enable(c); | | 122 | dtrace_interrupt_enable(c); |
105 | } | | 123 | } |
106 | | | 124 | |
107 | #ifdef __FreeBSD__ | | 125 | #ifdef __FreeBSD__ |
108 | | | 126 | |
109 | int | | 127 | int |
110 | fbt_provide_module_function(linker_file_t lf, int symindx, | | 128 | fbt_provide_module_function(linker_file_t lf, int symindx, |
111 | linker_symval_t *symval, void *opaque) | | 129 | linker_symval_t *symval, void *opaque) |
112 | { | | 130 | { |
113 | char *modname = opaque; | | 131 | char *modname = opaque; |
114 | const char *name = symval->name; | | 132 | const char *name = symval->name; |
115 | fbt_probe_t *fbt, *retfbt; | | 133 | fbt_probe_t *fbt, *retfbt; |
116 | uint32_t *instr, *limit; | | 134 | uint32_t *instr, *limit; |
117 | int popm; | | 135 | int popm; |
118 | | | 136 | |
119 | if (fbt_excluded(name)) | | 137 | if (fbt_excluded(name)) |
120 | return (0); | | 138 | return (0); |
121 | | | 139 | |
122 | instr = (uint32_t *)symval->value; | | 140 | instr = (uint32_t *)symval->value; |
123 | limit = (uint32_t *)(symval->value + symval->size); | | 141 | limit = (uint32_t *)(symval->value + symval->size); |
124 | | | 142 | |
125 | /* | | 143 | /* |
126 | * va_arg functions has first instruction of | | 144 | * va_arg functions has first instruction of |
127 | * sub sp, sp, #? | | 145 | * sub sp, sp, #? |
128 | */ | | 146 | */ |
129 | if ((*instr & 0xfffff000) == FBT_SUBSP) | | 147 | if ((ldinstr(instr) & 0xfffff000) == FBT_SUBSP) |
130 | instr++; | | 148 | instr++; |
131 | | | 149 | |
132 | /* | | 150 | /* |
133 | * check if insn is a pushm with LR | | 151 | * check if insn is a pushm with LR |
134 | */ | | 152 | */ |
135 | if ((*instr & 0xffff0000) != FBT_PUSHM || | | 153 | if ((ldinstr(instr) & 0xffff0000) != FBT_PUSHM || |
136 | (*instr & (1 << LR)) == 0) | | 154 | (ldinstr(instr) & (1 << LR)) == 0) |
137 | return (0); | | 155 | return (0); |
138 | | | 156 | |
139 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); | | 157 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); |
140 | fbt->fbtp_name = name; | | 158 | fbt->fbtp_name = name; |
141 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, | | 159 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, |
142 | name, FBT_ENTRY, 5, fbt); | | 160 | name, FBT_ENTRY, 5, fbt); |
143 | fbt->fbtp_patchpoint = instr; | | 161 | fbt->fbtp_patchpoint = instr; |
144 | fbt->fbtp_ctl = lf; | | 162 | fbt->fbtp_ctl = lf; |
145 | fbt->fbtp_loadcnt = lf->loadcnt; | | 163 | fbt->fbtp_loadcnt = lf->loadcnt; |
146 | fbt->fbtp_savedval = *instr; | | 164 | fbt->fbtp_savedval = ldinstr(instr); |
147 | fbt->fbtp_patchval = FBT_BREAKPOINT; | | 165 | fbt->fbtp_patchval = FBT_BREAKPOINT; |
148 | fbt->fbtp_rval = DTRACE_INVOP_PUSHM; | | 166 | fbt->fbtp_rval = DTRACE_INVOP_PUSHM; |
149 | fbt->fbtp_symindx = symindx; | | 167 | fbt->fbtp_symindx = symindx; |
150 | | | 168 | |
151 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; | | 169 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; |
152 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; | | 170 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; |
153 | | | 171 | |
154 | lf->fbt_nentries++; | | 172 | lf->fbt_nentries++; |
155 | | | 173 | |
156 | popm = FBT_POPM | ((*instr) & 0x3FFF) | 0x8000; | | 174 | popm = FBT_POPM | (ldinstr(instr) & 0x3FFF) | 0x8000; |
157 | | | 175 | |
158 | retfbt = NULL; | | 176 | retfbt = NULL; |
159 | again: | | 177 | again: |
160 | for (; instr < limit; instr++) { | | 178 | for (; instr < limit; instr++) { |
161 | if (*instr == popm) | | 179 | if (ldinstr(instr) == popm) |
162 | break; | | 180 | break; |
163 | else if ((*instr & 0xff000000) == FBT_JUMP) { | | 181 | else if ((ldinstr(instr) & 0xff000000) == FBT_JUMP) { |
164 | uint32_t *target, *start; | | 182 | uint32_t *target, *start; |
165 | int offset; | | 183 | int offset; |
166 | | | 184 | |
167 | offset = (*instr & 0xffffff); | | 185 | offset = (ldinstr(instr) & 0xffffff); |
168 | offset <<= 8; | | 186 | offset <<= 8; |
169 | offset /= 64; | | 187 | offset /= 64; |
170 | target = instr + (2 + offset); | | 188 | target = instr + (2 + offset); |
171 | start = (uint32_t *)symval->value; | | 189 | start = (uint32_t *)symval->value; |
172 | if (target >= limit || target < start) | | 190 | if (target >= limit || target < start) |
173 | break; | | 191 | break; |
174 | } | | 192 | } |
175 | } | | 193 | } |
176 | | | 194 | |
177 | if (instr >= limit) | | 195 | if (instr >= limit) |
178 | return (0); | | 196 | return (0); |
179 | | | 197 | |
180 | /* | | 198 | /* |
| @@ -185,31 +203,31 @@ again: | | | @@ -185,31 +203,31 @@ again: |
185 | if (retfbt == NULL) { | | 203 | if (retfbt == NULL) { |
186 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, | | 204 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, |
187 | name, FBT_RETURN, 5, fbt); | | 205 | name, FBT_RETURN, 5, fbt); |
188 | } else { | | 206 | } else { |
189 | retfbt->fbtp_next = fbt; | | 207 | retfbt->fbtp_next = fbt; |
190 | fbt->fbtp_id = retfbt->fbtp_id; | | 208 | fbt->fbtp_id = retfbt->fbtp_id; |
191 | } | | 209 | } |
192 | retfbt = fbt; | | 210 | retfbt = fbt; |
193 | | | 211 | |
194 | fbt->fbtp_patchpoint = instr; | | 212 | fbt->fbtp_patchpoint = instr; |
195 | fbt->fbtp_ctl = lf; | | 213 | fbt->fbtp_ctl = lf; |
196 | fbt->fbtp_loadcnt = lf->loadcnt; | | 214 | fbt->fbtp_loadcnt = lf->loadcnt; |
197 | fbt->fbtp_symindx = symindx; | | 215 | fbt->fbtp_symindx = symindx; |
198 | if ((*instr & 0xff000000) == FBT_JUMP) | | 216 | if ((ldinstr(instr) & 0xff000000) == FBT_JUMP) |
199 | fbt->fbtp_rval = DTRACE_INVOP_B; | | 217 | fbt->fbtp_rval = DTRACE_INVOP_B; |
200 | else | | 218 | else |
201 | fbt->fbtp_rval = DTRACE_INVOP_POPM; | | 219 | fbt->fbtp_rval = DTRACE_INVOP_POPM; |
202 | fbt->fbtp_savedval = *instr; | | 220 | fbt->fbtp_savedval = ldinstr(instr); |
203 | fbt->fbtp_patchval = FBT_BREAKPOINT; | | 221 | fbt->fbtp_patchval = FBT_BREAKPOINT; |
204 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; | | 222 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; |
205 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; | | 223 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; |
206 | | | 224 | |
207 | lf->fbt_nentries++; | | 225 | lf->fbt_nentries++; |
208 | | | 226 | |
209 | instr++; | | 227 | instr++; |
210 | goto again; | | 228 | goto again; |
211 | } | | 229 | } |
212 | | | 230 | |
213 | #endif /* __FreeBSD_ */ | | 231 | #endif /* __FreeBSD_ */ |
214 | | | 232 | |
215 | #ifdef __NetBSD__ | | 233 | #ifdef __NetBSD__ |
| @@ -269,90 +287,99 @@ fbt_provide_module_cb(const char *name, | | | @@ -269,90 +287,99 @@ fbt_provide_module_cb(const char *name, |
269 | strcmp(name, "binuptime") == 0 || | | 287 | strcmp(name, "binuptime") == 0 || |
270 | strcmp(name, "nanouptime") == 0 || | | 288 | strcmp(name, "nanouptime") == 0 || |
271 | strcmp(name, "dosoftints") == 0 || | | 289 | strcmp(name, "dosoftints") == 0 || |
272 | strcmp(name, "fbt_emulate") == 0 || | | 290 | strcmp(name, "fbt_emulate") == 0 || |
273 | strcmp(name, "undefinedinstruction") == 0 || | | 291 | strcmp(name, "undefinedinstruction") == 0 || |
274 | strncmp(name, "dmt_", 4) == 0 /* omap */ || | | 292 | strncmp(name, "dmt_", 4) == 0 /* omap */ || |
275 | strncmp(name, "mvsoctmr_", 9) == 0 /* marvell */ ) { | | 293 | strncmp(name, "mvsoctmr_", 9) == 0 /* marvell */ ) { |
276 | return 0; | | 294 | return 0; |
277 | } | | 295 | } |
278 | | | 296 | |
279 | instr = (uint32_t *) value; | | 297 | instr = (uint32_t *) value; |
280 | limit = (uint32_t *)((uintptr_t)value + symsize); | | 298 | limit = (uint32_t *)((uintptr_t)value + symsize); |
281 | | | 299 | |
282 | if (!FBT_MOV_IP_SP_P(*instr) | | 300 | if (!FBT_MOV_IP_SP_P(ldinstr(instr)) |
283 | && !FBT_BX_LR_P(*instr) | | 301 | && !FBT_BX_LR_P(ldinstr(instr)) |
284 | && !FBT_MOVW_P(*instr) | | 302 | && !FBT_MOVW_P(ldinstr(instr)) |
285 | && !FBT_MOV_IMM_P(*instr) | | 303 | && !FBT_MOV_IMM_P(ldinstr(instr)) |
286 | && !FBT_B_LABEL_P(*instr) | | 304 | && !FBT_B_LABEL_P(ldinstr(instr)) |
287 | && !FBT_LDR_IMM_P(*instr) | | 305 | && !FBT_LDR_IMM_P(ldinstr(instr)) |
288 | && !FBT_CMP_IMM_P(*instr) | | 306 | && !FBT_CMP_IMM_P(ldinstr(instr)) |
289 | && !FBT_PUSH_P(*instr) | | 307 | && !FBT_PUSH_P(ldinstr(instr)) |
290 | ) { | | 308 | ) { |
291 | return 0; | | 309 | return 0; |
292 | } | | 310 | } |
293 | | | 311 | |
294 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); | | 312 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); |
295 | fbt->fbtp_name = name; | | 313 | fbt->fbtp_name = name; |
296 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, | | 314 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, |
297 | name, FBT_ENTRY, 5, fbt); | | 315 | name, FBT_ENTRY, 5, fbt); |
298 | fbt->fbtp_patchpoint = instr; | | 316 | fbt->fbtp_patchpoint = instr; |
299 | fbt->fbtp_ctl = mod; | | 317 | fbt->fbtp_ctl = mod; |
300 | /* fbt->fbtp_loadcnt = lf->loadcnt; */ | | 318 | /* fbt->fbtp_loadcnt = lf->loadcnt; */ |
301 | if (FBT_MOV_IP_SP_P(*instr)) | | 319 | if (FBT_MOV_IP_SP_P(ldinstr(instr))) { |
302 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_IP_SP); | | 320 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
303 | else if (FBT_LDR_IMM_P(*instr)) | | 321 | DTRACE_INVOP_MOV_IP_SP); |
304 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_LDR_IMM); | | 322 | } else if (FBT_LDR_IMM_P(ldinstr(instr))) { |
305 | else if (FBT_MOVW_P(*instr)) | | 323 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
306 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOVW); | | 324 | DTRACE_INVOP_LDR_IMM); |
307 | else if (FBT_MOV_IMM_P(*instr)) | | 325 | } else if (FBT_MOVW_P(ldinstr(instr))) { |
308 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_IMM); | | 326 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), DTRACE_INVOP_MOVW); |
309 | else if (FBT_CMP_IMM_P(*instr)) | | 327 | } else if (FBT_MOV_IMM_P(ldinstr(instr))) { |
310 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_CMP_IMM); | | 328 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
311 | else if (FBT_BX_LR_P(*instr)) | | 329 | DTRACE_INVOP_MOV_IMM); |
312 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_BX_LR); | | 330 | } else if (FBT_CMP_IMM_P(ldinstr(instr))) { |
313 | else if (FBT_PUSH_P(*instr)) | | 331 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
314 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_PUSHM); | | 332 | DTRACE_INVOP_CMP_IMM); |
315 | else if (FBT_B_LABEL_P(*instr)) | | 333 | } else if (FBT_BX_LR_P(ldinstr(instr))) { |
316 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_B); | | 334 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
317 | else | | 335 | DTRACE_INVOP_BX_LR); |
| | | 336 | } else if (FBT_PUSH_P(ldinstr(instr))) { |
| | | 337 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
| | | 338 | DTRACE_INVOP_PUSHM); |
| | | 339 | } else if (FBT_B_LABEL_P(ldinstr(instr))) { |
| | | 340 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
| | | 341 | DTRACE_INVOP_B); |
| | | 342 | } else { |
318 | KASSERT(0); | | 343 | KASSERT(0); |
| | | 344 | } |
319 | | | 345 | |
320 | KASSERTMSG((fbt->fbtp_rval >> 28) != 0, | | 346 | KASSERTMSG((fbt->fbtp_rval >> 28) != 0, |
321 | "fbt %p insn 0x%x name %s rval 0x%08x", | | 347 | "fbt %p insn 0x%x name %s rval 0x%08x", |
322 | fbt, *instr, name, fbt->fbtp_rval); | | 348 | fbt, ldinstr(instr), name, fbt->fbtp_rval); |
323 | | | 349 | |
324 | fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(*instr); | | 350 | fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(ldinstr(instr)); |
325 | fbt->fbtp_savedval = *instr; | | 351 | fbt->fbtp_savedval = ldinstr(instr); |
326 | fbt->fbtp_symindx = symindx; | | 352 | fbt->fbtp_symindx = symindx; |
327 | | | 353 | |
328 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; | | 354 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; |
329 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; | | 355 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; |
330 | | | 356 | |
331 | retfbt = NULL; | | 357 | retfbt = NULL; |
332 | | | 358 | |
333 | while (instr < limit) { | | 359 | while (instr < limit) { |
334 | if (instr >= limit) | | 360 | if (instr >= limit) |
335 | return (0); | | 361 | return (0); |
336 | | | 362 | |
337 | size = 1; | | 363 | size = 1; |
338 | | | 364 | |
339 | if (!FBT_BX_LR_P(*instr) | | 365 | if (!FBT_BX_LR_P(ldinstr(instr)) |
340 | && !FBT_MOV_PC_LR_P(*instr) | | 366 | && !FBT_MOV_PC_LR_P(ldinstr(instr)) |
341 | && !FBT_LDM_P(*instr) | | 367 | && !FBT_LDM_P(ldinstr(instr)) |
342 | && !FBT_LDMIB_P(*instr) | | 368 | && !FBT_LDMIB_P(ldinstr(instr)) |
343 | && !(was_ldm_lr && FBT_B_LABEL_P(*instr)) | | 369 | && !(was_ldm_lr && FBT_B_LABEL_P(ldinstr(instr))) |
344 | ) { | | 370 | ) { |
345 | if (FBT_LDM_LR_P(*instr) || FBT_LDMIB_LR_P(*instr)) | | 371 | if (FBT_LDM_LR_P(ldinstr(instr)) || |
| | | 372 | FBT_LDMIB_LR_P(ldinstr(instr))) |
346 | was_ldm_lr = true; | | 373 | was_ldm_lr = true; |
347 | else | | 374 | else |
348 | was_ldm_lr = false; | | 375 | was_ldm_lr = false; |
349 | instr += size; | | 376 | instr += size; |
350 | continue; | | 377 | continue; |
351 | } | | 378 | } |
352 | | | 379 | |
353 | /* | | 380 | /* |
354 | * We have a winner! | | 381 | * We have a winner! |
355 | */ | | 382 | */ |
356 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); | | 383 | fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP); |
357 | fbt->fbtp_name = name; | | 384 | fbt->fbtp_name = name; |
358 | | | 385 | |
| @@ -360,44 +387,50 @@ fbt_provide_module_cb(const char *name, | | | @@ -360,44 +387,50 @@ fbt_provide_module_cb(const char *name, |
360 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, | | 387 | fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, |
361 | name, FBT_RETURN, 5, fbt); | | 388 | name, FBT_RETURN, 5, fbt); |
362 | } else { | | 389 | } else { |
363 | retfbt->fbtp_next = fbt; | | 390 | retfbt->fbtp_next = fbt; |
364 | fbt->fbtp_id = retfbt->fbtp_id; | | 391 | fbt->fbtp_id = retfbt->fbtp_id; |
365 | } | | 392 | } |
366 | | | 393 | |
367 | retfbt = fbt; | | 394 | retfbt = fbt; |
368 | fbt->fbtp_patchpoint = instr; | | 395 | fbt->fbtp_patchpoint = instr; |
369 | fbt->fbtp_ctl = mod; | | 396 | fbt->fbtp_ctl = mod; |
370 | /* fbt->fbtp_loadcnt = lf->loadcnt; */ | | 397 | /* fbt->fbtp_loadcnt = lf->loadcnt; */ |
371 | fbt->fbtp_symindx = symindx; | | 398 | fbt->fbtp_symindx = symindx; |
372 | | | 399 | |
373 | if (FBT_BX_LR_P(*instr)) | | 400 | if (FBT_BX_LR_P(ldinstr(instr))) { |
374 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_BX_LR); | | 401 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
375 | else if (FBT_MOV_PC_LR_P(*instr)) | | 402 | DTRACE_INVOP_BX_LR); |
376 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_PC_LR); | | 403 | } else if (FBT_MOV_PC_LR_P(ldinstr(instr))) { |
377 | else if (FBT_LDM_P(*instr)) | | 404 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
378 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_LDM); | | 405 | DTRACE_INVOP_MOV_PC_LR); |
379 | else if (FBT_LDMIB_P(*instr)) | | 406 | } else if (FBT_LDM_P(ldinstr(instr))) { |
380 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_POPM); | | 407 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
381 | else if (FBT_B_LABEL_P(*instr)) | | 408 | DTRACE_INVOP_LDM); |
382 | fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_B); | | 409 | } else if (FBT_LDMIB_P(ldinstr(instr))) { |
383 | else | | 410 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
| | | 411 | DTRACE_INVOP_POPM); |
| | | 412 | } else if (FBT_B_LABEL_P(ldinstr(instr))) { |
| | | 413 | fbt->fbtp_rval = BUILD_RVAL(ldinstr(instr), |
| | | 414 | DTRACE_INVOP_B); |
| | | 415 | } else { |
384 | KASSERT(0); | | 416 | KASSERT(0); |
| | | 417 | } |
385 | | | 418 | |
386 | KASSERTMSG((fbt->fbtp_rval >> 28) != 0, "fbt %p name %s rval 0x%08x", | | 419 | KASSERTMSG((fbt->fbtp_rval >> 28) != 0, "fbt %p name %s rval 0x%08x", |
387 | fbt, name, fbt->fbtp_rval); | | 420 | fbt, name, fbt->fbtp_rval); |
388 | | | 421 | |
389 | fbt->fbtp_roffset = (uintptr_t)(instr - (uint32_t *) value); | | 422 | fbt->fbtp_roffset = (uintptr_t)(instr - (uint32_t *) value); |
390 | fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(*instr); | | 423 | fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(ldinstr(instr)); |
391 | | | 424 | |
392 | fbt->fbtp_savedval = *instr; | | 425 | fbt->fbtp_savedval = ldinstr(instr); |
393 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; | | 426 | fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; |
394 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; | | 427 | fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; |
395 | | | 428 | |
396 | instr += size; | | 429 | instr += size; |
397 | was_ldm_lr = false; | | 430 | was_ldm_lr = false; |
398 | } | | 431 | } |
399 | | | 432 | |
400 | return 0; | | 433 | return 0; |
401 | } | | 434 | } |
402 | | | 435 | |
403 | #endif /* __NetBSD__ */ | | 436 | #endif /* __NetBSD__ */ |