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