1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * $FreeBSD$ 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 #include <sys/cdefs.h> 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 34 #include <machine/frame.h> 35 #include <machine/reg.h> 36 37 #include <machine/db_machdep.h> 38 #include <machine/vmparam.h> 39 #include <ddb/db_sym.h> 40 #include <ddb/ddb.h> 41 42 uintptr_t kernelbase = (uintptr_t)KERNEL_BASE; 43 44 /* TODO: support AAPCS */ 45 /* XXX: copied from sys/arch/arm/arm/db_trace.c */ 46 #define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS) 47 48 #define FR_SCP (0) 49 #define FR_RLV (-1) 50 #define FR_RSP (-2) 51 #define FR_RFP (-3) 52 53 #include "regset.h" 54 55 /* 56 * Wee need some reasonable default to prevent backtrace code 57 * from wandering too far 58 */ 59 #define MAX_FUNCTION_SIZE 0x10000 60 #define MAX_PROLOGUE_SIZE 0x100 61 62 63 uint8_t dtrace_fuword8_nocheck(void *); 64 uint16_t dtrace_fuword16_nocheck(void *); 65 uint32_t dtrace_fuword32_nocheck(void *); 66 uint64_t dtrace_fuword64_nocheck(void *); 67 68 void 69 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 70 uint32_t *intrpc) 71 { 72 uint32_t *frame, *lastframe; 73 #if 0 74 int scp_offset; 75 #endif 76 int depth = 0; 77 pc_t caller = (pc_t) solaris_cpu[cpu_number()].cpu_dtrace_caller; 78 79 if (intrpc != 0) 80 pcstack[depth++] = (pc_t) intrpc; 81 82 aframes++; 83 84 frame = (uint32_t *)__builtin_frame_address(0);; 85 lastframe = NULL; 86 #if 0 87 scp_offset = -(get_pc_str_offset() >> 2); 88 #endif 89 90 while ((frame != NULL) && (depth < pcstack_limit)) { 91 db_addr_t scp; 92 #if 0 93 uint32_t savecode; 94 int r; 95 uint32_t *rp; 96 #endif 97 98 /* 99 * In theory, the SCP isn't guaranteed to be in the function 100 * that generated the stack frame. We hope for the best. 101 */ 102 scp = frame[FR_SCP]; 103 printf("--> %08x\n", (uint32_t)scp); 104 105 if (aframes > 0) { 106 aframes--; 107 if ((aframes == 0) && (caller != 0)) { 108 pcstack[depth++] = caller; 109 } 110 } 111 else { 112 printf("++ --> %08x\n", (uint32_t)scp); 113 pcstack[depth++] = scp; 114 } 115 116 #if 0 117 savecode = ((uint32_t *)scp)[scp_offset]; 118 if ((savecode & 0x0e100000) == 0x08000000) { 119 /* Looks like an STM */ 120 rp = frame - 4; 121 for (r = 10; r >= 0; r--) { 122 if (savecode & (1 << r)) { 123 /* register r == *rp-- */ 124 } 125 } 126 } 127 #endif 128 129 /* 130 * Switch to next frame up 131 */ 132 if (frame[FR_RFP] == 0) 133 break; /* Top of stack */ 134 135 lastframe = frame; 136 frame = (uint32_t *)(frame[FR_RFP]); 137 138 if (INKERNEL((int)frame)) { 139 /* staying in kernel */ 140 if (frame <= lastframe) { 141 /* bad frame pointer */ 142 break; 143 } 144 } 145 else 146 break; 147 } 148 149 for (; depth < pcstack_limit; depth++) { 150 pcstack[depth] = 0; 151 } 152 } 153 154 void 155 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 156 { 157 printf("unimplemented\n"); 158 } 159 160 int 161 dtrace_getustackdepth(void) 162 { 163 printf("unimplemented\n"); 164 return (0); 165 } 166 167 void 168 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 169 { 170 printf("IMPLEMENT ME: %s\n", __func__); 171 } 172 173 /*ARGSUSED*/ 174 uint64_t 175 dtrace_getarg(int arg, int aframes) 176 { 177 printf("unimplemented\n"); 178 179 return (0); 180 } 181 182 int 183 dtrace_getstackdepth(int aframes) 184 { 185 uint32_t *frame, *lastframe; 186 int depth = 1; 187 188 frame = (uint32_t *)__builtin_frame_address(0);; 189 lastframe = NULL; 190 191 while (frame != NULL) { 192 #if 0 193 uint32_t savecode; 194 int r; 195 uint32_t *rp; 196 #endif 197 198 depth++; 199 200 /* 201 * Switch to next frame up 202 */ 203 if (frame[FR_RFP] == 0) 204 break; /* Top of stack */ 205 206 lastframe = frame; 207 frame = (uint32_t *)(frame[FR_RFP]); 208 209 if (INKERNEL((int)frame)) { 210 /* staying in kernel */ 211 if (frame <= lastframe) { 212 /* bad frame pointer */ 213 break; 214 } 215 } 216 else 217 break; 218 } 219 220 if (depth < aframes) 221 return 0; 222 else 223 return depth - aframes; 224 225 } 226 227 ulong_t 228 dtrace_getreg(struct regs *regs, uint_t reg) 229 { 230 231 return (0); 232 } 233 234 static int 235 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 236 { 237 238 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 239 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 240 cpu_core[cpu_number()].cpuc_dtrace_illval = uaddr; 241 return (0); 242 } 243 244 return (1); 245 } 246 247 void 248 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 249 volatile uint16_t *flags) 250 { 251 if (dtrace_copycheck(uaddr, kaddr, size)) 252 dtrace_copy(uaddr, kaddr, size); 253 } 254 255 void 256 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 257 volatile uint16_t *flags) 258 { 259 if (dtrace_copycheck(uaddr, kaddr, size)) 260 dtrace_copy(kaddr, uaddr, size); 261 } 262 263 void 264 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 265 volatile uint16_t *flags) 266 { 267 if (dtrace_copycheck(uaddr, kaddr, size)) 268 dtrace_copystr(uaddr, kaddr, size, flags); 269 } 270 271 void 272 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 273 volatile uint16_t *flags) 274 { 275 if (dtrace_copycheck(uaddr, kaddr, size)) 276 dtrace_copystr(kaddr, uaddr, size, flags); 277 } 278 279 uint8_t 280 dtrace_fuword8(void *uaddr) 281 { 282 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 283 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 284 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr; 285 return (0); 286 } 287 return (dtrace_fuword8_nocheck(uaddr)); 288 } 289 290 uint16_t 291 dtrace_fuword16(void *uaddr) 292 { 293 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 294 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 295 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr; 296 return (0); 297 } 298 return (dtrace_fuword16_nocheck(uaddr)); 299 } 300 301 uint32_t 302 dtrace_fuword32(void *uaddr) 303 { 304 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 305 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 306 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr; 307 return (0); 308 } 309 return (dtrace_fuword32_nocheck(uaddr)); 310 } 311 312 uint64_t 313 dtrace_fuword64(void *uaddr) 314 { 315 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 316 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 317 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr; 318 return (0); 319 } 320 return (dtrace_fuword64_nocheck(uaddr)); 321 } 322