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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <mdb/mdb_modapi.h> 28 #include <dtrace.h> 29 30 extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 31 extern const char *dof_sec_name(uint32_t); 32 33 extern const mdb_walker_t kernel_walkers[]; 34 extern const mdb_dcmd_t kernel_dcmds[]; 35 36 /*ARGSUSED*/ 37 static void 38 dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 39 { 40 mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name, 41 DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 42 } 43 44 /*ARGSUSED*/ 45 static void 46 dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 47 { 48 mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr)); 49 } 50 51 /*ARGSUSED*/ 52 static void 53 dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 54 { 55 mdb_printf("%-4s [%%r%u], %%r%u", name, 56 DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 57 } 58 59 /*ARGSUSED*/ 60 static void 61 dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 62 { 63 mdb_printf("%-4s %%r%u, [%%r%u]", name, 64 DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 65 } 66 67 /*ARGSUSED*/ 68 static void 69 dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 70 { 71 mdb_printf("%s", name); 72 } 73 74 /*ARGSUSED*/ 75 static void 76 dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 77 { 78 mdb_printf("%-4s %%r%u, %%r%u", name, 79 DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 80 } 81 82 /*ARGSUSED*/ 83 static void 84 dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 85 { 86 mdb_printf("%-4s %%r%u, %%r%u", name, 87 DIF_INSTR_R1(instr), DIF_INSTR_R2(instr)); 88 } 89 90 /*ARGSUSED*/ 91 static void 92 dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 93 { 94 mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr)); 95 } 96 97 static const char * 98 dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope) 99 { 100 dtrace_difv_t *dvp; 101 size_t varsize; 102 caddr_t addr = NULL, str; 103 uint_t i; 104 105 if (dp == NULL) 106 return (NULL); 107 108 varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 109 dvp = mdb_alloc(varsize, UM_SLEEP); 110 111 if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 112 mdb_free(dvp, varsize); 113 return ("<unreadable>"); 114 } 115 116 for (i = 0; i < dp->dtdo_varlen; i++) { 117 if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) { 118 if (dvp[i].dtdv_name < dp->dtdo_strlen) 119 addr = dp->dtdo_strtab + dvp[i].dtdv_name; 120 break; 121 } 122 } 123 124 mdb_free(dvp, varsize); 125 126 if (addr == NULL) 127 return (NULL); 128 129 str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC); 130 131 for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) { 132 if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1) 133 return ("<unreadable>"); 134 } 135 136 return (str); 137 } 138 139 static uint_t 140 dis_scope(const char *name) 141 { 142 switch (name[2]) { 143 case 'l': return (DIFV_SCOPE_LOCAL); 144 case 't': return (DIFV_SCOPE_THREAD); 145 case 'g': return (DIFV_SCOPE_GLOBAL); 146 default: return (-1u); 147 } 148 } 149 150 static void 151 dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 152 { 153 uint_t var = DIF_INSTR_R1(instr); 154 const char *vname; 155 156 mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name, 157 var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 158 159 if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 160 mdb_printf("\t\t! %s", vname); 161 } 162 163 static void 164 dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 165 { 166 uint_t var = DIF_INSTR_VAR(instr); 167 const char *vname; 168 169 mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr)); 170 171 if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 172 mdb_printf("\t\t! %s", vname); 173 } 174 175 static void 176 dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 177 { 178 uint_t var = DIF_INSTR_VAR(instr); 179 const char *vname; 180 181 mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var); 182 183 if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 184 mdb_printf("\t\t! %s", vname); 185 } 186 187 static void 188 dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 189 { 190 uint_t intptr = DIF_INSTR_INTEGER(instr); 191 192 mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name, 193 intptr, DIF_INSTR_RD(instr)); 194 195 if (dp != NULL && intptr < dp->dtdo_intlen) { 196 uint64_t *ip = mdb_alloc(dp->dtdo_intlen * 197 sizeof (uint64_t), UM_SLEEP | UM_GC); 198 199 if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t), 200 (uintptr_t)dp->dtdo_inttab) == -1) 201 mdb_warn("failed to read data at %p", dp->dtdo_inttab); 202 else 203 mdb_printf("\t\t! 0x%llx", ip[intptr]); 204 } 205 } 206 207 static void 208 dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 209 { 210 uint_t strptr = DIF_INSTR_STRING(instr); 211 212 mdb_printf("%-4s DIF_STRING[%u], %%r%u", name, 213 strptr, DIF_INSTR_RD(instr)); 214 215 if (dp != NULL && strptr < dp->dtdo_strlen) { 216 char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 217 218 if (mdb_vread(str, dp->dtdo_strlen, 219 (uintptr_t)dp->dtdo_strtab) == -1) 220 mdb_warn("failed to read data at %p", dp->dtdo_strtab); 221 else 222 mdb_printf("\t\t! \"%s\"", str + strptr); 223 } 224 } 225 226 /*ARGSUSED*/ 227 static void 228 dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 229 { 230 mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr)); 231 } 232 233 /*ARGSUSED*/ 234 static void 235 dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 236 { 237 uint_t subr = DIF_INSTR_SUBR(instr); 238 239 mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s", 240 name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr)); 241 } 242 243 /*ARGSUSED*/ 244 static void 245 dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 246 { 247 static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" }; 248 uint_t type = DIF_INSTR_TYPE(instr); 249 250 mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u", 251 name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr)); 252 253 if (type < sizeof (tnames) / sizeof (tnames[0])) 254 mdb_printf("\t\t! %s", tnames[type]); 255 } 256 257 /*ARGSUSED*/ 258 static void 259 dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 260 { 261 mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name, 262 DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr)); 263 } 264 265 static char * 266 dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len) 267 { 268 char kind[8]; 269 270 switch (t->dtdt_kind) { 271 case DIF_TYPE_CTF: 272 (void) strcpy(kind, "D type"); 273 break; 274 case DIF_TYPE_STRING: 275 (void) strcpy(kind, "string"); 276 break; 277 default: 278 (void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind); 279 } 280 281 if (t->dtdt_flags & DIF_TF_BYREF) { 282 (void) mdb_snprintf(buf, len, 283 "%s by ref (size %lu)", 284 kind, (ulong_t)t->dtdt_size); 285 } else { 286 (void) mdb_snprintf(buf, len, "%s (size %lu)", 287 kind, (ulong_t)t->dtdt_size); 288 } 289 290 return (buf); 291 } 292 293 static int 294 dis(uintptr_t addr, dtrace_difo_t *dp) 295 { 296 static const struct opent { 297 const char *op_name; 298 void (*op_func)(const dtrace_difo_t *, 299 const char *, dif_instr_t); 300 } optab[] = { 301 { "(illegal opcode)", dis_str }, 302 { "or", dis_log }, /* DIF_OP_OR */ 303 { "xor", dis_log }, /* DIF_OP_XOR */ 304 { "and", dis_log }, /* DIF_OP_AND */ 305 { "sll", dis_log }, /* DIF_OP_SLL */ 306 { "srl", dis_log }, /* DIF_OP_SRL */ 307 { "sub", dis_log }, /* DIF_OP_SUB */ 308 { "add", dis_log }, /* DIF_OP_ADD */ 309 { "mul", dis_log }, /* DIF_OP_MUL */ 310 { "sdiv", dis_log }, /* DIF_OP_SDIV */ 311 { "udiv", dis_log }, /* DIF_OP_UDIV */ 312 { "srem", dis_log }, /* DIF_OP_SREM */ 313 { "urem", dis_log }, /* DIF_OP_UREM */ 314 { "not", dis_r1rd }, /* DIF_OP_NOT */ 315 { "mov", dis_r1rd }, /* DIF_OP_MOV */ 316 { "cmp", dis_cmp }, /* DIF_OP_CMP */ 317 { "tst", dis_tst }, /* DIF_OP_TST */ 318 { "ba", dis_branch }, /* DIF_OP_BA */ 319 { "be", dis_branch }, /* DIF_OP_BE */ 320 { "bne", dis_branch }, /* DIF_OP_BNE */ 321 { "bg", dis_branch }, /* DIF_OP_BG */ 322 { "bgu", dis_branch }, /* DIF_OP_BGU */ 323 { "bge", dis_branch }, /* DIF_OP_BGE */ 324 { "bgeu", dis_branch }, /* DIF_OP_BGEU */ 325 { "bl", dis_branch }, /* DIF_OP_BL */ 326 { "blu", dis_branch }, /* DIF_OP_BLU */ 327 { "ble", dis_branch }, /* DIF_OP_BLE */ 328 { "bleu", dis_branch }, /* DIF_OP_BLEU */ 329 { "ldsb", dis_load }, /* DIF_OP_LDSB */ 330 { "ldsh", dis_load }, /* DIF_OP_LDSH */ 331 { "ldsw", dis_load }, /* DIF_OP_LDSW */ 332 { "ldub", dis_load }, /* DIF_OP_LDUB */ 333 { "lduh", dis_load }, /* DIF_OP_LDUH */ 334 { "lduw", dis_load }, /* DIF_OP_LDUW */ 335 { "ldx", dis_load }, /* DIF_OP_LDX */ 336 { "ret", dis_ret }, /* DIF_OP_RET */ 337 { "nop", dis_str }, /* DIF_OP_NOP */ 338 { "setx", dis_setx }, /* DIF_OP_SETX */ 339 { "sets", dis_sets }, /* DIF_OP_SETS */ 340 { "scmp", dis_cmp }, /* DIF_OP_SCMP */ 341 { "ldga", dis_lda }, /* DIF_OP_LDGA */ 342 { "ldgs", dis_ldv }, /* DIF_OP_LDGS */ 343 { "stgs", dis_stv }, /* DIF_OP_STGS */ 344 { "ldta", dis_lda }, /* DIF_OP_LDTA */ 345 { "ldts", dis_ldv }, /* DIF_OP_LDTS */ 346 { "stts", dis_stv }, /* DIF_OP_STTS */ 347 { "sra", dis_log }, /* DIF_OP_SRA */ 348 { "call", dis_call }, /* DIF_OP_CALL */ 349 { "pushtr", dis_pushts }, /* DIF_OP_PUSHTR */ 350 { "pushtv", dis_pushts }, /* DIF_OP_PUSHTV */ 351 { "popts", dis_str }, /* DIF_OP_POPTS */ 352 { "flushts", dis_str }, /* DIF_OP_FLUSHTS */ 353 { "ldgaa", dis_ldv }, /* DIF_OP_LDGAA */ 354 { "ldtaa", dis_ldv }, /* DIF_OP_LDTAA */ 355 { "stgaa", dis_stv }, /* DIF_OP_STGAA */ 356 { "sttaa", dis_stv }, /* DIF_OP_STTAA */ 357 { "ldls", dis_ldv }, /* DIF_OP_LDLS */ 358 { "stls", dis_stv }, /* DIF_OP_STLS */ 359 { "allocs", dis_r1rd }, /* DIF_OP_ALLOCS */ 360 { "copys", dis_log }, /* DIF_OP_COPYS */ 361 { "stb", dis_store }, /* DIF_OP_STB */ 362 { "sth", dis_store }, /* DIF_OP_STH */ 363 { "stw", dis_store }, /* DIF_OP_STW */ 364 { "stx", dis_store }, /* DIF_OP_STX */ 365 { "uldsb", dis_load }, /* DIF_OP_ULDSB */ 366 { "uldsh", dis_load }, /* DIF_OP_ULDSH */ 367 { "uldsw", dis_load }, /* DIF_OP_ULDSW */ 368 { "uldub", dis_load }, /* DIF_OP_ULDUB */ 369 { "ulduh", dis_load }, /* DIF_OP_ULDUH */ 370 { "ulduw", dis_load }, /* DIF_OP_ULDUW */ 371 { "uldx", dis_load }, /* DIF_OP_ULDX */ 372 { "rldsb", dis_load }, /* DIF_OP_RLDSB */ 373 { "rldsh", dis_load }, /* DIF_OP_RLDSH */ 374 { "rldsw", dis_load }, /* DIF_OP_RLDSW */ 375 { "rldub", dis_load }, /* DIF_OP_RLDUB */ 376 { "rlduh", dis_load }, /* DIF_OP_RLDUH */ 377 { "rlduw", dis_load }, /* DIF_OP_RLDUW */ 378 { "rldx", dis_load }, /* DIF_OP_RLDX */ 379 { "xlate", dis_xlate }, /* DIF_OP_XLATE */ 380 { "xlarg", dis_xlate }, /* DIF_OP_XLARG */ 381 }; 382 383 dif_instr_t instr, opcode; 384 const struct opent *op; 385 386 if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) { 387 mdb_warn("failed to read DIF instruction at %p", addr); 388 return (DCMD_ERR); 389 } 390 391 opcode = DIF_INSTR_OP(instr); 392 393 if (opcode >= sizeof (optab) / sizeof (optab[0])) 394 opcode = 0; /* force invalid opcode message */ 395 396 op = &optab[opcode]; 397 mdb_printf("%0?p %08x ", addr, instr); 398 op->op_func(dp, op->op_name, instr); 399 mdb_printf("\n"); 400 mdb_set_dot(addr + sizeof (dif_instr_t)); 401 402 return (DCMD_OK); 403 } 404 405 /*ARGSUSED*/ 406 int 407 difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 408 { 409 dtrace_difo_t difo, *dp = &difo; 410 uintptr_t instr, limit; 411 dtrace_difv_t *dvp; 412 size_t varsize; 413 ulong_t i; 414 char type[64]; 415 char *str; 416 417 if (!(flags & DCMD_ADDRSPEC)) 418 return (DCMD_USAGE); 419 420 if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) { 421 mdb_warn("couldn't read dtrace_difo_t at %p", addr); 422 return (DCMD_ERR); 423 } 424 425 mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n", 426 addr, dp->dtdo_refcnt); 427 mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION"); 428 429 mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf); 430 limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t); 431 432 while ((instr = mdb_get_dot()) < limit) 433 dis(instr, dp); 434 435 if (dp->dtdo_varlen != 0) { 436 mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n", 437 "NAME", "ID", "KND", "SCP", "FLAG", "TYPE"); 438 } 439 440 varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 441 dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC); 442 443 if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 444 mdb_warn("couldn't read dtdo_vartab"); 445 return (DCMD_ERR); 446 } 447 448 str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 449 450 if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) { 451 mdb_warn("couldn't read dtdo_strtab"); 452 return (DCMD_ERR); 453 } 454 455 for (i = 0; i < dp->dtdo_varlen; i++) { 456 dtrace_difv_t *v = &dvp[i]; 457 char kind[4], scope[4], flags[16] = { 0 }; 458 459 switch (v->dtdv_kind) { 460 case DIFV_KIND_ARRAY: 461 (void) strcpy(kind, "arr"); 462 break; 463 case DIFV_KIND_SCALAR: 464 (void) strcpy(kind, "scl"); 465 break; 466 default: 467 (void) mdb_snprintf(kind, sizeof (kind), 468 "%u", v->dtdv_kind); 469 } 470 471 switch (v->dtdv_scope) { 472 case DIFV_SCOPE_GLOBAL: 473 (void) strcpy(scope, "glb"); 474 break; 475 case DIFV_SCOPE_THREAD: 476 (void) strcpy(scope, "tls"); 477 break; 478 case DIFV_SCOPE_LOCAL: 479 (void) strcpy(scope, "loc"); 480 break; 481 default: 482 (void) mdb_snprintf(scope, sizeof (scope), 483 "%u", v->dtdv_scope); 484 } 485 486 if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) { 487 (void) mdb_snprintf(flags, sizeof (flags), "/0x%x", 488 v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)); 489 } 490 491 if (v->dtdv_flags & DIFV_F_REF) 492 (void) strcat(flags, "/r"); 493 if (v->dtdv_flags & DIFV_F_MOD) 494 (void) strcat(flags, "/w"); 495 496 mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n", 497 &str[v->dtdv_name], 498 v->dtdv_id, kind, scope, flags + 1, 499 dis_typestr(&v->dtdv_type, type, sizeof (type))); 500 } 501 502 mdb_printf("\n%<b>RETURN%</b>\n%s\n\n", 503 dis_typestr(&dp->dtdo_rtype, type, sizeof (type))); 504 505 return (DCMD_OK); 506 } 507 508 /*ARGSUSED*/ 509 int 510 difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 511 { 512 if (!(flags & DCMD_ADDRSPEC)) 513 return (DCMD_USAGE); 514 515 return (dis(addr, NULL)); 516 } 517 518 /*ARGSUSED*/ 519 int 520 dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 521 { 522 dof_hdr_t h; 523 524 if (argc != 0) 525 return (DCMD_USAGE); 526 527 if (!(flags & DCMD_ADDRSPEC)) 528 addr = 0; /* assume base of file in file target */ 529 530 if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 531 mdb_warn("failed to read header at %p", addr); 532 return (DCMD_ERR); 533 } 534 535 mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n", 536 h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1], 537 h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]); 538 539 switch (h.dofh_ident[DOF_ID_MODEL]) { 540 case DOF_MODEL_ILP32: 541 mdb_printf("dofh_ident.id_model = ILP32\n"); 542 break; 543 case DOF_MODEL_LP64: 544 mdb_printf("dofh_ident.id_model = LP64\n"); 545 break; 546 default: 547 mdb_printf("dofh_ident.id_model = 0x%x\n", 548 h.dofh_ident[DOF_ID_MODEL]); 549 } 550 551 switch (h.dofh_ident[DOF_ID_ENCODING]) { 552 case DOF_ENCODE_LSB: 553 mdb_printf("dofh_ident.id_encoding = LSB\n"); 554 break; 555 case DOF_ENCODE_MSB: 556 mdb_printf("dofh_ident.id_encoding = MSB\n"); 557 break; 558 default: 559 mdb_printf("dofh_ident.id_encoding = 0x%x\n", 560 h.dofh_ident[DOF_ID_ENCODING]); 561 } 562 563 mdb_printf("dofh_ident.id_version = %u\n", 564 h.dofh_ident[DOF_ID_VERSION]); 565 mdb_printf("dofh_ident.id_difvers = %u\n", 566 h.dofh_ident[DOF_ID_DIFVERS]); 567 mdb_printf("dofh_ident.id_difireg = %u\n", 568 h.dofh_ident[DOF_ID_DIFIREG]); 569 mdb_printf("dofh_ident.id_diftreg = %u\n", 570 h.dofh_ident[DOF_ID_DIFTREG]); 571 572 mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags); 573 mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize); 574 mdb_printf("dofh_secsize = %u\n", h.dofh_secsize); 575 mdb_printf("dofh_secnum = %u\n", h.dofh_secnum); 576 mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff); 577 mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz); 578 mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz); 579 580 return (DCMD_OK); 581 } 582 583 /*ARGSUSED*/ 584 static int 585 dof_sec_walk(uintptr_t addr, void *ignored, int *sec) 586 { 587 mdb_printf("%3d ", (*sec)++); 588 (void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 589 return (WALK_NEXT); 590 } 591 592 /*ARGSUSED*/ 593 int 594 dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 595 { 596 const char *name; 597 dof_sec_t s; 598 599 if (!(flags & DCMD_ADDRSPEC)) 600 mdb_printf("%<u>%-3s ", "NDX"); 601 602 if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 603 mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 604 "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET", 605 "SIZE"); 606 } 607 608 if (!(flags & DCMD_ADDRSPEC)) { 609 int sec = 0; 610 611 if (mdb_walk("dof_sec", 612 (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) { 613 mdb_warn("failed to walk dof_sec"); 614 return (DCMD_ERR); 615 } 616 return (DCMD_OK); 617 } 618 619 if (argc != 0) 620 return (DCMD_USAGE); 621 622 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 623 mdb_warn("failed to read section header at %p", addr); 624 return (DCMD_ERR); 625 } 626 627 mdb_printf("%?p ", addr); 628 629 if ((name = dof_sec_name(s.dofs_type)) != NULL) 630 mdb_printf("%-10s ", name); 631 else 632 mdb_printf("%-10u ", s.dofs_type); 633 634 mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align, 635 s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size); 636 637 return (DCMD_OK); 638 } 639 640 int 641 dof_sec_walk_init(mdb_walk_state_t *wsp) 642 { 643 dof_hdr_t h, *hp; 644 size_t size; 645 646 if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 647 mdb_warn("failed to read DOF header at %p", wsp->walk_addr); 648 return (WALK_ERR); 649 } 650 651 size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum; 652 hp = mdb_alloc(size, UM_SLEEP); 653 654 if (mdb_vread(hp, size, wsp->walk_addr) != size) { 655 mdb_warn("failed to read DOF sections at %p", wsp->walk_addr); 656 mdb_free(hp, size); 657 return (WALK_ERR); 658 } 659 660 wsp->walk_arg = (void *)0; 661 wsp->walk_data = hp; 662 663 return (WALK_NEXT); 664 } 665 666 int 667 dof_sec_walk_step(mdb_walk_state_t *wsp) 668 { 669 uint_t i = (uintptr_t)wsp->walk_arg; 670 size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i; 671 dof_hdr_t *hp = wsp->walk_data; 672 dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off); 673 674 if (i >= hp->dofh_secnum) 675 return (WALK_DONE); 676 677 wsp->walk_arg = (void *)(uintptr_t)(i + 1); 678 return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 679 } 680 681 void 682 dof_sec_walk_fini(mdb_walk_state_t *wsp) 683 { 684 dof_hdr_t *hp = wsp->walk_data; 685 mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum); 686 } 687 688 /*ARGSUSED*/ 689 int 690 dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 691 { 692 dof_ecbdesc_t e; 693 694 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 695 return (DCMD_USAGE); 696 697 if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) { 698 mdb_warn("failed to read ecbdesc at %p", addr); 699 return (DCMD_ERR); 700 } 701 702 mdb_printf("dofe_probes = %d\n", e.dofe_probes); 703 mdb_printf("dofe_actions = %d\n", e.dofe_actions); 704 mdb_printf("dofe_pred = %d\n", e.dofe_pred); 705 mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg); 706 707 return (DCMD_OK); 708 } 709 710 /*ARGSUSED*/ 711 int 712 dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 713 { 714 dof_probedesc_t p; 715 716 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 717 return (DCMD_USAGE); 718 719 if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) { 720 mdb_warn("failed to read probedesc at %p", addr); 721 return (DCMD_ERR); 722 } 723 724 mdb_printf("dofp_strtab = %d\n", p.dofp_strtab); 725 mdb_printf("dofp_provider = %u\n", p.dofp_provider); 726 mdb_printf("dofp_mod = %u\n", p.dofp_mod); 727 mdb_printf("dofp_func = %u\n", p.dofp_func); 728 mdb_printf("dofp_name = %u\n", p.dofp_name); 729 mdb_printf("dofp_id = %u\n", p.dofp_id); 730 731 return (DCMD_OK); 732 } 733 734 /*ARGSUSED*/ 735 int 736 dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 737 { 738 dof_actdesc_t a; 739 740 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 741 return (DCMD_USAGE); 742 743 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 744 mdb_warn("failed to read actdesc at %p", addr); 745 return (DCMD_ERR); 746 } 747 748 mdb_printf("dofa_difo = %d\n", a.dofa_difo); 749 mdb_printf("dofa_strtab = %d\n", a.dofa_strtab); 750 mdb_printf("dofa_kind = %u\n", a.dofa_kind); 751 mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple); 752 mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg); 753 mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg); 754 755 return (DCMD_OK); 756 } 757 758 /*ARGSUSED*/ 759 int 760 dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 761 { 762 dof_relohdr_t r; 763 764 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 765 return (DCMD_USAGE); 766 767 if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 768 mdb_warn("failed to read relohdr at %p", addr); 769 return (DCMD_ERR); 770 } 771 772 mdb_printf("dofr_strtab = %d\n", r.dofr_strtab); 773 mdb_printf("dofr_relsec = %d\n", r.dofr_relsec); 774 mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec); 775 776 return (DCMD_OK); 777 } 778 779 /*ARGSUSED*/ 780 int 781 dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 782 { 783 dof_relodesc_t r; 784 785 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 786 return (DCMD_USAGE); 787 788 if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 789 mdb_warn("failed to read relodesc at %p", addr); 790 return (DCMD_ERR); 791 } 792 793 mdb_printf("dofr_name = %u\n", r.dofr_name); 794 mdb_printf("dofr_type = %u\n", r.dofr_type); 795 mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset); 796 mdb_printf("dofr_data = 0x%llx\n", r.dofr_data); 797 798 return (DCMD_OK); 799 } 800 801 static int 802 dof_sect_strtab(uintptr_t addr, dof_sec_t *sec) 803 { 804 char *strtab; 805 size_t sz, i; 806 807 sz = (size_t)sec->dofs_size; 808 strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 809 if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) { 810 mdb_warn("failed to read string table"); 811 return (1); 812 } 813 814 mdb_printf("size = %lx\n", sz); 815 816 for (i = 0; i < sz; i++) { 817 if (strtab[i] == '\0') 818 mdb_printf("\\0"); 819 else 820 mdb_printf("%c", strtab[i]); 821 } 822 823 mdb_printf("\n"); 824 825 return (0); 826 } 827 828 static int 829 dof_sect_provider(dof_hdr_t *dofh, uintptr_t addr, dof_sec_t *sec, 830 dof_sec_t *dofs) 831 { 832 dof_provider_t pv; 833 dof_probe_t *pb; 834 char *strtab, *p; 835 uint32_t *offs, *enoffs; 836 uint8_t *args = NULL; 837 size_t sz; 838 int i, j; 839 dof_stridx_t narg, xarg; 840 841 sz = MIN(sec->dofs_size, sizeof (dof_provider_t)); 842 if (mdb_vread(&pv, sz, addr + sec->dofs_offset) != sz) { 843 mdb_warn("failed to read DOF provider"); 844 return (-1); 845 } 846 847 sz = dofs[pv.dofpv_strtab].dofs_size; 848 strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 849 if (mdb_vread(strtab, sz, addr + 850 dofs[pv.dofpv_strtab].dofs_offset) != sz) { 851 mdb_warn("failed to read string table"); 852 return (-1); 853 } 854 855 mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset), 856 strtab + pv.dofpv_name); 857 858 sz = dofs[pv.dofpv_prargs].dofs_size; 859 if (sz != 0) { 860 args = mdb_alloc(sz, UM_SLEEP | UM_GC); 861 if (mdb_vread(args, sz, addr + 862 dofs[pv.dofpv_prargs].dofs_offset) != sz) { 863 mdb_warn("failed to read args"); 864 return (-1); 865 } 866 } 867 868 sz = dofs[pv.dofpv_proffs].dofs_size; 869 offs = mdb_alloc(sz, UM_SLEEP | UM_GC); 870 if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset) 871 != sz) { 872 mdb_warn("failed to read offsets"); 873 return (-1); 874 } 875 876 enoffs = NULL; 877 if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 || 878 pv.dofpv_prenoffs == 0) { 879 sz = dofs[pv.dofpv_prenoffs].dofs_size; 880 enoffs = mdb_alloc(sz, UM_SLEEP | UM_GC); 881 if (mdb_vread(enoffs, sz, addr + 882 dofs[pv.dofpv_prenoffs].dofs_offset) != sz) { 883 mdb_warn("failed to read is-enabled offsets"); 884 return (-1); 885 } 886 } 887 888 sz = dofs[pv.dofpv_probes].dofs_size; 889 p = mdb_alloc(sz, UM_SLEEP | UM_GC); 890 if (mdb_vread(p, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) { 891 mdb_warn("failed to read probes"); 892 return (-1); 893 } 894 895 (void) mdb_inc_indent(2); 896 897 for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) { 898 pb = (dof_probe_t *)(uintptr_t)(p + 899 i * dofs[pv.dofpv_probes].dofs_entsize); 900 901 mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr + 902 dofs[pv.dofpv_probes].dofs_offset + 903 i * dofs[pv.dofpv_probes].dofs_entsize), 904 strtab + pb->dofpr_func, 905 strtab + pb->dofpr_name); 906 907 (void) mdb_inc_indent(2); 908 mdb_printf("addr: %p\n", (ulong_t)pb->dofpr_addr); 909 mdb_printf("offs: "); 910 for (j = 0; j < pb->dofpr_noffs; j++) { 911 mdb_printf("%s %x", "," + (j == 0), 912 offs[pb->dofpr_offidx + j]); 913 } 914 mdb_printf("\n"); 915 916 if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) { 917 mdb_printf("enoffs: "); 918 if (enoffs == NULL) { 919 if (pb->dofpr_nenoffs != 0) 920 mdb_printf("<error>"); 921 } else { 922 for (j = 0; j < pb->dofpr_nenoffs; j++) { 923 mdb_printf("%s %x", "," + (j == 0), 924 enoffs[pb->dofpr_enoffidx + j]); 925 } 926 } 927 mdb_printf("\n"); 928 } 929 930 mdb_printf("nargs:"); 931 narg = pb->dofpr_nargv; 932 for (j = 0; j < pb->dofpr_nargc; j++) { 933 mdb_printf("%s %s", "," + (j == 0), strtab + narg); 934 narg += strlen(strtab + narg) + 1; 935 } 936 mdb_printf("\n"); 937 mdb_printf("xargs:"); 938 xarg = pb->dofpr_xargv; 939 for (j = 0; j < pb->dofpr_xargc; j++) { 940 mdb_printf("%s %s", "," + (j == 0), strtab + xarg); 941 xarg += strlen(strtab + xarg) + 1; 942 } 943 mdb_printf("\n"); 944 mdb_printf("map: "); 945 for (j = 0; j < pb->dofpr_xargc; j++) { 946 mdb_printf("%s %d->%d", "," + (j == 0), 947 args[pb->dofpr_argidx + j], j); 948 } 949 950 (void) mdb_dec_indent(2); 951 mdb_printf("\n}\n"); 952 } 953 954 (void) mdb_dec_indent(2); 955 mdb_printf("}\n"); 956 957 return (0); 958 } 959 960 static int 961 dof_sect_prargs(uintptr_t addr, dof_sec_t *sec) 962 { 963 int i; 964 uint8_t arg; 965 966 for (i = 0; i < sec->dofs_size; i++) { 967 if (mdb_vread(&arg, sizeof (arg), 968 addr + sec->dofs_offset + i) != sizeof (arg)) { 969 mdb_warn("failed to read argument"); 970 return (1); 971 } 972 973 mdb_printf("%d ", arg); 974 975 if (i % 20 == 19) 976 mdb_printf("\n"); 977 } 978 979 mdb_printf("\n"); 980 981 return (0); 982 } 983 984 /*ARGSUSED*/ 985 static int 986 dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 987 { 988 dof_hdr_t dofh; 989 dof_sec_t *dofs; 990 const char *name; 991 int i; 992 993 if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) { 994 mdb_warn("failed to read DOF header"); 995 return (DCMD_ERR); 996 } 997 998 dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum, 999 UM_SLEEP | UM_GC); 1000 1001 for (i = 0; i < dofh.dofh_secnum; i++) { 1002 if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff + 1003 addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) { 1004 mdb_warn("failed to read DOF sections"); 1005 return (DCMD_ERR); 1006 } 1007 } 1008 1009 for (i = 0; i < dofh.dofh_secnum; i++) { 1010 mdb_printf("%lx Section %d: ", (ulong_t) 1011 (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i); 1012 1013 if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL) 1014 mdb_printf("%s\n", name); 1015 else 1016 mdb_printf("%u\n", dofs[i].dofs_type); 1017 1018 (void) mdb_inc_indent(2); 1019 switch (dofs[i].dofs_type) { 1020 case DOF_SECT_PROVIDER: 1021 (void) dof_sect_provider(&dofh, addr, &dofs[i], dofs); 1022 break; 1023 case DOF_SECT_STRTAB: 1024 (void) dof_sect_strtab(addr, &dofs[i]); 1025 break; 1026 case DOF_SECT_PRARGS: 1027 (void) dof_sect_prargs(addr, &dofs[i]); 1028 break; 1029 } 1030 (void) mdb_dec_indent(2); 1031 1032 mdb_printf("\n"); 1033 } 1034 1035 return (DCMD_OK); 1036 } 1037 1038 static const mdb_dcmd_t common_dcmds[] = { 1039 { "difinstr", ":", "disassemble a DIF instruction", difinstr }, 1040 { "difo", ":", "print a DIF object", difo }, 1041 { "dof_hdr", "?", "print a DOF header", dof_hdr }, 1042 { "dof_sec", ":", "print a DOF section header", dof_sec }, 1043 { "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc }, 1044 { "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc }, 1045 { "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc }, 1046 { "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr }, 1047 { "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc }, 1048 { "dofdump", ":", "dump DOF", dofdump }, 1049 { NULL } 1050 }; 1051 1052 static const mdb_walker_t common_walkers[] = { 1053 { "dof_sec", "walk DOF section header table given header address", 1054 dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini }, 1055 { NULL } 1056 }; 1057 1058 static mdb_modinfo_t modinfo = { 1059 MDB_API_VERSION, NULL, NULL 1060 }; 1061 1062 const mdb_modinfo_t * 1063 _mdb_init(void) 1064 { 1065 uint_t d = 0, kd = 0, w = 0, kw = 0; 1066 const mdb_walker_t *wp; 1067 const mdb_dcmd_t *dp; 1068 1069 for (dp = common_dcmds; dp->dc_name != NULL; dp++) 1070 d++; /* count common dcmds */ 1071 1072 for (wp = common_walkers; wp->walk_name != NULL; wp++) 1073 w++; /* count common walkers */ 1074 1075 #ifdef _KERNEL 1076 for (dp = kernel_dcmds; dp->dc_name != NULL; dp++) 1077 kd++; /* count kernel dcmds */ 1078 1079 for (wp = kernel_walkers; wp->walk_name != NULL; wp++) 1080 kw++; /* count common walkers */ 1081 #endif 1082 1083 modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP); 1084 modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP); 1085 1086 bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d); 1087 bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w); 1088 1089 #ifdef _KERNEL 1090 bcopy(kernel_dcmds, (void *) 1091 (modinfo.mi_dcmds + d), sizeof (*dp) * kd); 1092 bcopy(kernel_walkers, (void *) 1093 (modinfo.mi_walkers + w), sizeof (*wp) * kw); 1094 #endif 1095 return (&modinfo); 1096 } 1097 1098 void 1099 _mdb_fini(void) 1100 { 1101 const mdb_walker_t *wp; 1102 const mdb_dcmd_t *dp; 1103 uint_t d = 0, w = 0; 1104 1105 for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++) 1106 d++; 1107 1108 for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++) 1109 w++; 1110 1111 mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1)); 1112 mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1)); 1113 } 1114