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