1265Smws /* 2265Smws * CDDL HEADER START 3265Smws * 4265Smws * The contents of this file are subject to the terms of the 5265Smws * Common Development and Distribution License, Version 1.0 only 6265Smws * (the "License"). You may not use this file except in compliance 7265Smws * with the License. 8265Smws * 9265Smws * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10265Smws * or http://www.opensolaris.org/os/licensing. 11265Smws * See the License for the specific language governing permissions 12265Smws * and limitations under the License. 13265Smws * 14265Smws * When distributing Covered Code, include this CDDL HEADER in each 15265Smws * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16265Smws * If applicable, add the following below this CDDL HEADER, with the 17265Smws * fields enclosed by brackets "[]" replaced with your own identifying 18265Smws * information: Portions Copyright [yyyy] [name of copyright owner] 19265Smws * 20265Smws * CDDL HEADER END 21265Smws */ 22265Smws /* 23265Smws * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24265Smws * Use is subject to license terms. 25265Smws */ 26265Smws 27265Smws #pragma ident "%Z%%M% %I% %E% SMI" 28265Smws 29265Smws #include <mdb/mdb_modapi.h> 30265Smws #include <dtrace.h> 31265Smws 32265Smws extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 33265Smws extern const char *dof_sec_name(uint32_t); 34265Smws 35265Smws extern const mdb_walker_t kernel_walkers[]; 36265Smws extern const mdb_dcmd_t kernel_dcmds[]; 37265Smws 38265Smws /*ARGSUSED*/ 39265Smws static void 40265Smws dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 41265Smws { 42265Smws mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name, 43265Smws DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 44265Smws } 45265Smws 46265Smws /*ARGSUSED*/ 47265Smws static void 48265Smws dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 49265Smws { 50265Smws mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr)); 51265Smws } 52265Smws 53265Smws /*ARGSUSED*/ 54265Smws static void 55265Smws dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 56265Smws { 57265Smws mdb_printf("%-4s [%%r%u], %%r%u", name, 58265Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 59265Smws } 60265Smws 61265Smws /*ARGSUSED*/ 62265Smws static void 63265Smws dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 64265Smws { 65265Smws mdb_printf("%-4s %%r%u, [%%r%u]", name, 66265Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 67265Smws } 68265Smws 69265Smws /*ARGSUSED*/ 70265Smws static void 71265Smws dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 72265Smws { 73265Smws mdb_printf("%s", name); 74265Smws } 75265Smws 76265Smws /*ARGSUSED*/ 77265Smws static void 78265Smws dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 79265Smws { 80265Smws mdb_printf("%-4s %%r%u, %%r%u", name, 81265Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 82265Smws } 83265Smws 84265Smws /*ARGSUSED*/ 85265Smws static void 86265Smws dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 87265Smws { 88265Smws mdb_printf("%-4s %%r%u, %%r%u", name, 89265Smws DIF_INSTR_R1(instr), DIF_INSTR_R2(instr)); 90265Smws } 91265Smws 92265Smws /*ARGSUSED*/ 93265Smws static void 94265Smws dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 95265Smws { 96265Smws mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr)); 97265Smws } 98265Smws 99265Smws static const char * 100265Smws dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope) 101265Smws { 102265Smws dtrace_difv_t *dvp; 103265Smws size_t varsize; 104265Smws caddr_t addr = NULL, str; 105265Smws uint_t i; 106265Smws 107265Smws if (dp == NULL) 108265Smws return (NULL); 109265Smws 110265Smws varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 111265Smws dvp = mdb_alloc(varsize, UM_SLEEP); 112265Smws 113265Smws if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 114265Smws mdb_free(dvp, varsize); 115265Smws return ("<unreadable>"); 116265Smws } 117265Smws 118265Smws for (i = 0; i < dp->dtdo_varlen; i++) { 119265Smws if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) { 120265Smws if (dvp[i].dtdv_name < dp->dtdo_strlen) 121265Smws addr = dp->dtdo_strtab + dvp[i].dtdv_name; 122265Smws break; 123265Smws } 124265Smws } 125265Smws 126265Smws mdb_free(dvp, varsize); 127265Smws 128265Smws if (addr == NULL) 129265Smws return (NULL); 130265Smws 131265Smws str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC); 132265Smws 133265Smws for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) { 134265Smws if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1) 135265Smws return ("<unreadable>"); 136265Smws } 137265Smws 138265Smws return (str); 139265Smws } 140265Smws 141265Smws static uint_t 142265Smws dis_scope(const char *name) 143265Smws { 144265Smws switch (name[2]) { 145265Smws case 'l': return (DIFV_SCOPE_LOCAL); 146265Smws case 't': return (DIFV_SCOPE_THREAD); 147265Smws case 'g': return (DIFV_SCOPE_GLOBAL); 148265Smws default: return (-1u); 149265Smws } 150265Smws } 151265Smws 152265Smws static void 153265Smws dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 154265Smws { 155265Smws uint_t var = DIF_INSTR_R1(instr); 156265Smws const char *vname; 157265Smws 158265Smws mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name, 159265Smws var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 160265Smws 161265Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 162265Smws mdb_printf("\t\t! %s", vname); 163265Smws } 164265Smws 165265Smws static void 166265Smws dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 167265Smws { 168265Smws uint_t var = DIF_INSTR_VAR(instr); 169265Smws const char *vname; 170265Smws 171265Smws mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr)); 172265Smws 173265Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 174265Smws mdb_printf("\t\t! %s", vname); 175265Smws } 176265Smws 177265Smws static void 178265Smws dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 179265Smws { 180265Smws uint_t var = DIF_INSTR_VAR(instr); 181265Smws const char *vname; 182265Smws 183265Smws mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var); 184265Smws 185265Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 186265Smws mdb_printf("\t\t! %s", vname); 187265Smws } 188265Smws 189265Smws static void 190265Smws dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 191265Smws { 192265Smws uint_t intptr = DIF_INSTR_INTEGER(instr); 193265Smws 194265Smws mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name, 195265Smws intptr, DIF_INSTR_RD(instr)); 196265Smws 197265Smws if (dp != NULL && intptr < dp->dtdo_intlen) { 198265Smws uint64_t *ip = mdb_alloc(dp->dtdo_intlen * 199265Smws sizeof (uint64_t), UM_SLEEP | UM_GC); 200265Smws 201265Smws if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t), 202265Smws (uintptr_t)dp->dtdo_inttab) == -1) 203265Smws mdb_warn("failed to read data at %p", dp->dtdo_inttab); 204265Smws else 205265Smws mdb_printf("\t\t! 0x%llx", ip[intptr]); 206265Smws } 207265Smws } 208265Smws 209265Smws static void 210265Smws dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 211265Smws { 212265Smws uint_t strptr = DIF_INSTR_STRING(instr); 213265Smws 214265Smws mdb_printf("%-4s DIF_STRING[%u], %%r%u", name, 215265Smws strptr, DIF_INSTR_RD(instr)); 216265Smws 217265Smws if (dp != NULL && strptr < dp->dtdo_strlen) { 218265Smws char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 219265Smws 220265Smws if (mdb_vread(str, dp->dtdo_strlen, 221265Smws (uintptr_t)dp->dtdo_strtab) == -1) 222265Smws mdb_warn("failed to read data at %p", dp->dtdo_strtab); 223265Smws else 224265Smws mdb_printf("\t\t! \"%s\"", str + strptr); 225265Smws } 226265Smws } 227265Smws 228265Smws /*ARGSUSED*/ 229265Smws static void 230265Smws dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 231265Smws { 232265Smws mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr)); 233265Smws } 234265Smws 235265Smws /*ARGSUSED*/ 236265Smws static void 237265Smws dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 238265Smws { 239265Smws uint_t subr = DIF_INSTR_SUBR(instr); 240265Smws 241265Smws mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s", 242265Smws name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr)); 243265Smws } 244265Smws 245265Smws /*ARGSUSED*/ 246265Smws static void 247265Smws dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 248265Smws { 249265Smws static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" }; 250265Smws uint_t type = DIF_INSTR_TYPE(instr); 251265Smws 252265Smws mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u", 253265Smws name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr)); 254265Smws 255265Smws if (type < sizeof (tnames) / sizeof (tnames[0])) 256*491Sbmc mdb_printf("\t\t! %s", tnames[type]); 257265Smws } 258265Smws 259265Smws /*ARGSUSED*/ 260265Smws static void 261265Smws dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 262265Smws { 263265Smws mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name, 264265Smws DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr)); 265265Smws } 266265Smws 267265Smws static char * 268265Smws dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len) 269265Smws { 270265Smws char kind[8]; 271265Smws 272265Smws switch (t->dtdt_kind) { 273265Smws case DIF_TYPE_CTF: 274265Smws (void) strcpy(kind, "D type"); 275265Smws break; 276265Smws case DIF_TYPE_STRING: 277265Smws (void) strcpy(kind, "string"); 278265Smws break; 279265Smws default: 280265Smws (void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind); 281265Smws } 282265Smws 283265Smws if (t->dtdt_flags & DIF_TF_BYREF) { 284265Smws (void) mdb_snprintf(buf, len, 285265Smws "%s by ref (size %lu)", 286265Smws kind, (ulong_t)t->dtdt_size); 287265Smws } else { 288265Smws (void) mdb_snprintf(buf, len, "%s (size %lu)", 289265Smws kind, (ulong_t)t->dtdt_size); 290265Smws } 291265Smws 292265Smws return (buf); 293265Smws } 294265Smws 295265Smws static int 296265Smws dis(uintptr_t addr, dtrace_difo_t *dp) 297265Smws { 298265Smws static const struct opent { 299265Smws const char *op_name; 300265Smws void (*op_func)(const dtrace_difo_t *, 301265Smws const char *, dif_instr_t); 302265Smws } optab[] = { 303265Smws { "(illegal opcode)", dis_str }, 304265Smws { "or", dis_log }, /* DIF_OP_OR */ 305265Smws { "xor", dis_log }, /* DIF_OP_XOR */ 306265Smws { "and", dis_log }, /* DIF_OP_AND */ 307265Smws { "sll", dis_log }, /* DIF_OP_SLL */ 308265Smws { "srl", dis_log }, /* DIF_OP_SRL */ 309265Smws { "sub", dis_log }, /* DIF_OP_SUB */ 310265Smws { "add", dis_log }, /* DIF_OP_ADD */ 311265Smws { "mul", dis_log }, /* DIF_OP_MUL */ 312265Smws { "sdiv", dis_log }, /* DIF_OP_SDIV */ 313265Smws { "udiv", dis_log }, /* DIF_OP_UDIV */ 314265Smws { "srem", dis_log }, /* DIF_OP_SREM */ 315265Smws { "urem", dis_log }, /* DIF_OP_UREM */ 316265Smws { "not", dis_r1rd }, /* DIF_OP_NOT */ 317265Smws { "mov", dis_r1rd }, /* DIF_OP_MOV */ 318265Smws { "cmp", dis_cmp }, /* DIF_OP_CMP */ 319265Smws { "tst", dis_tst }, /* DIF_OP_TST */ 320265Smws { "ba", dis_branch }, /* DIF_OP_BA */ 321265Smws { "be", dis_branch }, /* DIF_OP_BE */ 322265Smws { "bne", dis_branch }, /* DIF_OP_BNE */ 323265Smws { "bg", dis_branch }, /* DIF_OP_BG */ 324265Smws { "bgu", dis_branch }, /* DIF_OP_BGU */ 325265Smws { "bge", dis_branch }, /* DIF_OP_BGE */ 326265Smws { "bgeu", dis_branch }, /* DIF_OP_BGEU */ 327265Smws { "bl", dis_branch }, /* DIF_OP_BL */ 328265Smws { "blu", dis_branch }, /* DIF_OP_BLU */ 329265Smws { "ble", dis_branch }, /* DIF_OP_BLE */ 330265Smws { "bleu", dis_branch }, /* DIF_OP_BLEU */ 331265Smws { "ldsb", dis_load }, /* DIF_OP_LDSB */ 332265Smws { "ldsh", dis_load }, /* DIF_OP_LDSH */ 333265Smws { "ldsw", dis_load }, /* DIF_OP_LDSW */ 334265Smws { "ldub", dis_load }, /* DIF_OP_LDUB */ 335265Smws { "lduh", dis_load }, /* DIF_OP_LDUH */ 336265Smws { "lduw", dis_load }, /* DIF_OP_LDUW */ 337265Smws { "ldx", dis_load }, /* DIF_OP_LDX */ 338265Smws { "ret", dis_ret }, /* DIF_OP_RET */ 339265Smws { "nop", dis_str }, /* DIF_OP_NOP */ 340265Smws { "setx", dis_setx }, /* DIF_OP_SETX */ 341265Smws { "sets", dis_sets }, /* DIF_OP_SETS */ 342265Smws { "scmp", dis_cmp }, /* DIF_OP_SCMP */ 343265Smws { "ldga", dis_lda }, /* DIF_OP_LDGA */ 344265Smws { "ldgs", dis_ldv }, /* DIF_OP_LDGS */ 345265Smws { "stgs", dis_stv }, /* DIF_OP_STGS */ 346265Smws { "ldta", dis_lda }, /* DIF_OP_LDTA */ 347265Smws { "ldts", dis_ldv }, /* DIF_OP_LDTS */ 348265Smws { "stts", dis_stv }, /* DIF_OP_STTS */ 349265Smws { "sra", dis_log }, /* DIF_OP_SRA */ 350265Smws { "call", dis_call }, /* DIF_OP_CALL */ 351265Smws { "pushtr", dis_pushts }, /* DIF_OP_PUSHTR */ 352265Smws { "pushtv", dis_pushts }, /* DIF_OP_PUSHTV */ 353265Smws { "popts", dis_str }, /* DIF_OP_POPTS */ 354265Smws { "flushts", dis_str }, /* DIF_OP_FLUSHTS */ 355265Smws { "ldgaa", dis_ldv }, /* DIF_OP_LDGAA */ 356265Smws { "ldtaa", dis_ldv }, /* DIF_OP_LDTAA */ 357265Smws { "stgaa", dis_stv }, /* DIF_OP_STGAA */ 358265Smws { "sttaa", dis_stv }, /* DIF_OP_STTAA */ 359265Smws { "ldls", dis_ldv }, /* DIF_OP_LDLS */ 360265Smws { "stls", dis_stv }, /* DIF_OP_STLS */ 361265Smws { "allocs", dis_r1rd }, /* DIF_OP_ALLOCS */ 362265Smws { "copys", dis_log }, /* DIF_OP_COPYS */ 363265Smws { "stb", dis_store }, /* DIF_OP_STB */ 364265Smws { "sth", dis_store }, /* DIF_OP_STH */ 365265Smws { "stw", dis_store }, /* DIF_OP_STW */ 366265Smws { "stx", dis_store }, /* DIF_OP_STX */ 367265Smws { "uldsb", dis_load }, /* DIF_OP_ULDSB */ 368265Smws { "uldsh", dis_load }, /* DIF_OP_ULDSH */ 369265Smws { "uldsw", dis_load }, /* DIF_OP_ULDSW */ 370265Smws { "uldub", dis_load }, /* DIF_OP_ULDUB */ 371265Smws { "ulduh", dis_load }, /* DIF_OP_ULDUH */ 372265Smws { "ulduw", dis_load }, /* DIF_OP_ULDUW */ 373265Smws { "uldx", dis_load }, /* DIF_OP_ULDX */ 374265Smws { "rldsb", dis_load }, /* DIF_OP_RLDSB */ 375265Smws { "rldsh", dis_load }, /* DIF_OP_RLDSH */ 376265Smws { "rldsw", dis_load }, /* DIF_OP_RLDSW */ 377265Smws { "rldub", dis_load }, /* DIF_OP_RLDUB */ 378265Smws { "rlduh", dis_load }, /* DIF_OP_RLDUH */ 379265Smws { "rlduw", dis_load }, /* DIF_OP_RLDUW */ 380265Smws { "rldx", dis_load }, /* DIF_OP_RLDX */ 381265Smws { "xlate", dis_xlate }, /* DIF_OP_XLATE */ 382265Smws { "xlarg", dis_xlate }, /* DIF_OP_XLARG */ 383265Smws }; 384265Smws 385265Smws dif_instr_t instr, opcode; 386265Smws const struct opent *op; 387265Smws 388265Smws if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) { 389265Smws mdb_warn("failed to read DIF instruction at %p", addr); 390265Smws return (DCMD_ERR); 391265Smws } 392265Smws 393265Smws opcode = DIF_INSTR_OP(instr); 394265Smws 395265Smws if (opcode >= sizeof (optab) / sizeof (optab[0])) 396265Smws opcode = 0; /* force invalid opcode message */ 397265Smws 398265Smws op = &optab[opcode]; 399*491Sbmc mdb_printf("%0?p %08x ", addr, instr); 400265Smws op->op_func(dp, op->op_name, instr); 401265Smws mdb_printf("\n"); 402265Smws mdb_set_dot(addr + sizeof (dif_instr_t)); 403265Smws 404265Smws return (DCMD_OK); 405265Smws } 406265Smws 407265Smws /*ARGSUSED*/ 408265Smws int 409265Smws difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 410265Smws { 411265Smws dtrace_difo_t difo, *dp = &difo; 412265Smws uintptr_t instr, limit; 413265Smws dtrace_difv_t *dvp; 414265Smws size_t varsize; 415265Smws ulong_t i; 416265Smws char type[64]; 417265Smws char *str; 418265Smws 419265Smws if (!(flags & DCMD_ADDRSPEC)) 420265Smws return (DCMD_USAGE); 421265Smws 422265Smws if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) { 423265Smws mdb_warn("couldn't read dtrace_difo_t at %p", addr); 424265Smws return (DCMD_ERR); 425265Smws } 426265Smws 427265Smws mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n", 428265Smws addr, dp->dtdo_refcnt); 429*491Sbmc mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION"); 430265Smws 431265Smws mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf); 432265Smws limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t); 433265Smws 434265Smws while ((instr = mdb_get_dot()) < limit) 435265Smws dis(instr, dp); 436265Smws 437265Smws if (dp->dtdo_varlen != 0) { 438265Smws mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n", 439265Smws "NAME", "ID", "KND", "SCP", "FLAG", "TYPE"); 440265Smws } 441265Smws 442265Smws varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 443265Smws dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC); 444265Smws 445265Smws if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 446265Smws mdb_warn("couldn't read dtdo_vartab"); 447265Smws return (DCMD_ERR); 448265Smws } 449265Smws 450265Smws str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 451265Smws 452265Smws if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) { 453265Smws mdb_warn("couldn't read dtdo_strtab"); 454265Smws return (DCMD_ERR); 455265Smws } 456265Smws 457265Smws for (i = 0; i < dp->dtdo_varlen; i++) { 458265Smws dtrace_difv_t *v = &dvp[i]; 459265Smws char kind[4], scope[4], flags[16] = { 0 }; 460265Smws 461265Smws switch (v->dtdv_kind) { 462265Smws case DIFV_KIND_ARRAY: 463265Smws (void) strcpy(kind, "arr"); 464265Smws break; 465265Smws case DIFV_KIND_SCALAR: 466265Smws (void) strcpy(kind, "scl"); 467265Smws break; 468265Smws default: 469265Smws (void) mdb_snprintf(kind, sizeof (kind), 470265Smws "%u", v->dtdv_kind); 471265Smws } 472265Smws 473265Smws switch (v->dtdv_scope) { 474265Smws case DIFV_SCOPE_GLOBAL: 475265Smws (void) strcpy(scope, "glb"); 476265Smws break; 477265Smws case DIFV_SCOPE_THREAD: 478265Smws (void) strcpy(scope, "tls"); 479265Smws break; 480265Smws case DIFV_SCOPE_LOCAL: 481265Smws (void) strcpy(scope, "loc"); 482265Smws break; 483265Smws default: 484265Smws (void) mdb_snprintf(scope, sizeof (scope), 485265Smws "%u", v->dtdv_scope); 486265Smws } 487265Smws 488265Smws if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) { 489265Smws (void) mdb_snprintf(flags, sizeof (flags), "/0x%x", 490265Smws v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)); 491265Smws } 492265Smws 493265Smws if (v->dtdv_flags & DIFV_F_REF) 494265Smws (void) strcat(flags, "/r"); 495265Smws if (v->dtdv_flags & DIFV_F_MOD) 496265Smws (void) strcat(flags, "/w"); 497265Smws 498265Smws mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n", 499265Smws &str[v->dtdv_name], 500265Smws v->dtdv_id, kind, scope, flags + 1, 501265Smws dis_typestr(&v->dtdv_type, type, sizeof (type))); 502265Smws } 503265Smws 504265Smws mdb_printf("\n%<b>RETURN%</b>\n%s\n\n", 505265Smws dis_typestr(&dp->dtdo_rtype, type, sizeof (type))); 506265Smws 507265Smws return (DCMD_OK); 508265Smws } 509265Smws 510265Smws /*ARGSUSED*/ 511265Smws int 512265Smws difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 513265Smws { 514265Smws if (!(flags & DCMD_ADDRSPEC)) 515265Smws return (DCMD_USAGE); 516265Smws 517265Smws return (dis(addr, NULL)); 518265Smws } 519265Smws 520265Smws /*ARGSUSED*/ 521265Smws int 522265Smws dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 523265Smws { 524265Smws dof_hdr_t h; 525265Smws 526265Smws if (argc != 0) 527265Smws return (DCMD_USAGE); 528265Smws 529265Smws if (!(flags & DCMD_ADDRSPEC)) 530265Smws addr = 0; /* assume base of file in file target */ 531265Smws 532265Smws if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 533265Smws mdb_warn("failed to read header at %p", addr); 534265Smws return (DCMD_ERR); 535265Smws } 536265Smws 537265Smws mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n", 538265Smws h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1], 539265Smws h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]); 540265Smws 541265Smws switch (h.dofh_ident[DOF_ID_MODEL]) { 542265Smws case DOF_MODEL_ILP32: 543265Smws mdb_printf("dofh_ident.id_model = ILP32\n"); 544265Smws break; 545265Smws case DOF_MODEL_LP64: 546265Smws mdb_printf("dofh_ident.id_model = LP64\n"); 547265Smws break; 548265Smws default: 549265Smws mdb_printf("dofh_ident.id_model = 0x%x\n", 550265Smws h.dofh_ident[DOF_ID_MODEL]); 551265Smws } 552265Smws 553265Smws switch (h.dofh_ident[DOF_ID_ENCODING]) { 554265Smws case DOF_ENCODE_LSB: 555265Smws mdb_printf("dofh_ident.id_encoding = LSB\n"); 556265Smws break; 557265Smws case DOF_ENCODE_MSB: 558265Smws mdb_printf("dofh_ident.id_encoding = MSB\n"); 559265Smws break; 560265Smws default: 561265Smws mdb_printf("dofh_ident.id_encoding = 0x%x\n", 562265Smws h.dofh_ident[DOF_ID_ENCODING]); 563265Smws } 564265Smws 565265Smws mdb_printf("dofh_ident.id_version = %u\n", 566265Smws h.dofh_ident[DOF_ID_VERSION]); 567265Smws mdb_printf("dofh_ident.id_difvers = %u\n", 568265Smws h.dofh_ident[DOF_ID_DIFVERS]); 569265Smws mdb_printf("dofh_ident.id_difireg = %u\n", 570265Smws h.dofh_ident[DOF_ID_DIFIREG]); 571265Smws mdb_printf("dofh_ident.id_diftreg = %u\n", 572265Smws h.dofh_ident[DOF_ID_DIFTREG]); 573265Smws 574265Smws mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags); 575265Smws mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize); 576265Smws mdb_printf("dofh_secsize = %u\n", h.dofh_secsize); 577265Smws mdb_printf("dofh_secnum = %u\n", h.dofh_secnum); 578265Smws mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff); 579265Smws mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz); 580265Smws mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz); 581265Smws 582265Smws return (DCMD_OK); 583265Smws } 584265Smws 585265Smws /*ARGSUSED*/ 586265Smws static int 587265Smws dof_sec_walk(uintptr_t addr, void *ignored, int *sec) 588265Smws { 589265Smws mdb_printf("%3d ", (*sec)++); 590265Smws (void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 591265Smws return (WALK_NEXT); 592265Smws } 593265Smws 594265Smws /*ARGSUSED*/ 595265Smws int 596265Smws dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 597265Smws { 598265Smws const char *name; 599265Smws dof_sec_t s; 600265Smws 601265Smws if (!(flags & DCMD_ADDRSPEC)) 602265Smws mdb_printf("%<u>%-3s ", "NDX"); 603265Smws 604265Smws if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 605265Smws mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 606265Smws "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET", 607265Smws "SIZE"); 608265Smws } 609265Smws 610265Smws if (!(flags & DCMD_ADDRSPEC)) { 611265Smws int sec = 0; 612265Smws 613265Smws if (mdb_walk("dof_sec", 614265Smws (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) { 615265Smws mdb_warn("failed to walk dof_sec"); 616265Smws return (DCMD_ERR); 617265Smws } 618265Smws return (DCMD_OK); 619265Smws } 620265Smws 621265Smws if (argc != 0) 622265Smws return (DCMD_USAGE); 623265Smws 624265Smws if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 625265Smws mdb_warn("failed to read section header at %p", addr); 626265Smws return (DCMD_ERR); 627265Smws } 628265Smws 629265Smws mdb_printf("%?p ", addr); 630265Smws 631265Smws if ((name = dof_sec_name(s.dofs_type)) != NULL) 632265Smws mdb_printf("%-10s ", name); 633265Smws else 634265Smws mdb_printf("%-10u ", s.dofs_type); 635265Smws 636265Smws mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align, 637265Smws s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size); 638265Smws 639265Smws return (DCMD_OK); 640265Smws } 641265Smws 642265Smws int 643265Smws dof_sec_walk_init(mdb_walk_state_t *wsp) 644265Smws { 645265Smws dof_hdr_t h, *hp; 646265Smws size_t size; 647265Smws 648265Smws if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 649265Smws mdb_warn("failed to read DOF header at %p", wsp->walk_addr); 650265Smws return (WALK_ERR); 651265Smws } 652265Smws 653265Smws size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum; 654265Smws hp = mdb_alloc(size, UM_SLEEP); 655265Smws 656265Smws if (mdb_vread(hp, size, wsp->walk_addr) != size) { 657265Smws mdb_warn("failed to read DOF sections at %p", wsp->walk_addr); 658265Smws mdb_free(hp, size); 659265Smws return (WALK_ERR); 660265Smws } 661265Smws 662265Smws wsp->walk_arg = (void *)0; 663265Smws wsp->walk_data = hp; 664265Smws 665265Smws return (WALK_NEXT); 666265Smws } 667265Smws 668265Smws int 669265Smws dof_sec_walk_step(mdb_walk_state_t *wsp) 670265Smws { 671265Smws uint_t i = (uintptr_t)wsp->walk_arg; 672265Smws size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i; 673265Smws dof_hdr_t *hp = wsp->walk_data; 674265Smws dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off); 675265Smws 676265Smws if (i >= hp->dofh_secnum) 677265Smws return (WALK_DONE); 678265Smws 679265Smws wsp->walk_arg = (void *)(uintptr_t)(i + 1); 680265Smws return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 681265Smws } 682265Smws 683265Smws void 684265Smws dof_sec_walk_fini(mdb_walk_state_t *wsp) 685265Smws { 686265Smws dof_hdr_t *hp = wsp->walk_data; 687265Smws mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum); 688265Smws } 689265Smws 690265Smws /*ARGSUSED*/ 691265Smws int 692265Smws dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 693265Smws { 694265Smws dof_ecbdesc_t e; 695265Smws 696265Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 697265Smws return (DCMD_USAGE); 698265Smws 699265Smws if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) { 700265Smws mdb_warn("failed to read ecbdesc at %p", addr); 701265Smws return (DCMD_ERR); 702265Smws } 703265Smws 704265Smws mdb_printf("dofe_probes = %d\n", e.dofe_probes); 705265Smws mdb_printf("dofe_actions = %d\n", e.dofe_actions); 706265Smws mdb_printf("dofe_pred = %d\n", e.dofe_pred); 707265Smws mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg); 708265Smws 709265Smws return (DCMD_OK); 710265Smws } 711265Smws 712265Smws /*ARGSUSED*/ 713265Smws int 714265Smws dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 715265Smws { 716265Smws dof_probedesc_t p; 717265Smws 718265Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 719265Smws return (DCMD_USAGE); 720265Smws 721265Smws if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) { 722265Smws mdb_warn("failed to read probedesc at %p", addr); 723265Smws return (DCMD_ERR); 724265Smws } 725265Smws 726265Smws mdb_printf("dofp_strtab = %d\n", p.dofp_strtab); 727265Smws mdb_printf("dofp_provider = %u\n", p.dofp_provider); 728265Smws mdb_printf("dofp_mod = %u\n", p.dofp_mod); 729265Smws mdb_printf("dofp_func = %u\n", p.dofp_func); 730265Smws mdb_printf("dofp_name = %u\n", p.dofp_name); 731265Smws mdb_printf("dofp_id = %u\n", p.dofp_id); 732265Smws 733265Smws return (DCMD_OK); 734265Smws } 735265Smws 736265Smws /*ARGSUSED*/ 737265Smws int 738265Smws dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 739265Smws { 740265Smws dof_actdesc_t a; 741265Smws 742265Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 743265Smws return (DCMD_USAGE); 744265Smws 745265Smws if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 746265Smws mdb_warn("failed to read actdesc at %p", addr); 747265Smws return (DCMD_ERR); 748265Smws } 749265Smws 750265Smws mdb_printf("dofa_difo = %d\n", a.dofa_difo); 751265Smws mdb_printf("dofa_strtab = %d\n", a.dofa_strtab); 752265Smws mdb_printf("dofa_kind = %u\n", a.dofa_kind); 753265Smws mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple); 754265Smws mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg); 755265Smws mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg); 756265Smws 757265Smws return (DCMD_OK); 758265Smws } 759265Smws 760265Smws /*ARGSUSED*/ 761265Smws int 762265Smws dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 763265Smws { 764265Smws dof_relohdr_t r; 765265Smws 766265Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 767265Smws return (DCMD_USAGE); 768265Smws 769265Smws if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 770265Smws mdb_warn("failed to read relohdr at %p", addr); 771265Smws return (DCMD_ERR); 772265Smws } 773265Smws 774265Smws mdb_printf("dofr_strtab = %d\n", r.dofr_strtab); 775265Smws mdb_printf("dofr_relsec = %d\n", r.dofr_relsec); 776265Smws mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec); 777265Smws 778265Smws return (DCMD_OK); 779265Smws } 780265Smws 781265Smws /*ARGSUSED*/ 782265Smws int 783265Smws dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 784265Smws { 785265Smws dof_relodesc_t r; 786265Smws 787265Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 788265Smws return (DCMD_USAGE); 789265Smws 790265Smws if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 791265Smws mdb_warn("failed to read relodesc at %p", addr); 792265Smws return (DCMD_ERR); 793265Smws } 794265Smws 795265Smws mdb_printf("dofr_name = %u\n", r.dofr_name); 796265Smws mdb_printf("dofr_type = %u\n", r.dofr_type); 797265Smws mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset); 798265Smws mdb_printf("dofr_data = 0x%llx\n", r.dofr_data); 799265Smws 800265Smws return (DCMD_OK); 801265Smws } 802265Smws 803265Smws static int 804265Smws dof_sect_strtab(uintptr_t addr, dof_sec_t *sec) 805265Smws { 806265Smws char *strtab; 807265Smws size_t sz, i; 808265Smws 809265Smws sz = (size_t)sec->dofs_size; 810265Smws strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 811265Smws if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) { 812265Smws mdb_warn("failed to read string table"); 813265Smws return (1); 814265Smws } 815265Smws 816265Smws mdb_printf("size = %lx\n", sz); 817265Smws 818265Smws for (i = 0; i < sz; i++) { 819265Smws if (strtab[i] == '\0') 820265Smws mdb_printf("\\0"); 821265Smws else 822265Smws mdb_printf("%c", strtab[i]); 823265Smws } 824265Smws 825265Smws mdb_printf("\n"); 826265Smws 827265Smws return (0); 828265Smws } 829265Smws 830265Smws static int 831265Smws dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs) 832265Smws { 833265Smws dof_provider_t pv; 834265Smws dof_probe_t *pb; 835265Smws char *strtab; 836265Smws uint32_t *offs; 837265Smws uint8_t *args = NULL; 838265Smws size_t sz; 839265Smws int i, j; 840265Smws dof_stridx_t narg, xarg; 841265Smws 842265Smws if (mdb_vread(&pv, sizeof (dof_provider_t), 843265Smws addr + sec->dofs_offset) != sizeof (dof_provider_t)) { 844265Smws mdb_warn("failed to read DOF provider"); 845265Smws return (-1); 846265Smws } 847265Smws 848265Smws sz = dofs[pv.dofpv_strtab].dofs_size; 849265Smws strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 850265Smws if (mdb_vread(strtab, sz, addr + 851265Smws dofs[pv.dofpv_strtab].dofs_offset) != sz) { 852265Smws mdb_warn("failed to read string table"); 853265Smws return (-1); 854265Smws } 855265Smws 856265Smws mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset), 857265Smws strtab + pv.dofpv_name); 858265Smws 859265Smws sz = dofs[pv.dofpv_prargs].dofs_size; 860265Smws if (sz != 0) { 861265Smws args = mdb_alloc(sz, UM_SLEEP | UM_GC); 862265Smws if (mdb_vread(args, sz, addr + 863265Smws dofs[pv.dofpv_prargs].dofs_offset) != sz) { 864265Smws mdb_warn("failed to read args"); 865265Smws return (-1); 866265Smws } 867265Smws } 868265Smws 869265Smws sz = dofs[pv.dofpv_proffs].dofs_size; 870265Smws offs = mdb_alloc(sz, UM_SLEEP | UM_GC); 871265Smws if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset) 872265Smws != sz) { 873265Smws mdb_warn("failed to read offs"); 874265Smws return (-1); 875265Smws } 876265Smws 877265Smws sz = dofs[pv.dofpv_probes].dofs_size; 878265Smws pb = mdb_alloc(sz, UM_SLEEP | UM_GC); 879265Smws if (mdb_vread(pb, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) { 880265Smws mdb_warn("failed to read probes"); 881265Smws return (-1); 882265Smws } 883265Smws 884265Smws (void) mdb_inc_indent(2); 885265Smws 886265Smws for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) { 887265Smws mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr + 888265Smws dofs[pv.dofpv_probes].dofs_offset + 889265Smws i * dofs[pv.dofpv_probes].dofs_entsize), 890265Smws strtab + pb[i].dofpr_func, 891265Smws strtab + pb[i].dofpr_name); 892265Smws 893265Smws (void) mdb_inc_indent(2); 894265Smws mdb_printf("addr: %p\n", (ulong_t)pb[i].dofpr_addr); 895265Smws mdb_printf("offs: "); 896265Smws for (j = 0; j < pb[i].dofpr_noffs; j++) { 897265Smws mdb_printf("%s %x", "," + (j == 0), 898265Smws offs[pb[i].dofpr_offidx + j]); 899265Smws } 900265Smws mdb_printf("\n"); 901265Smws 902265Smws mdb_printf("nargs:"); 903265Smws narg = pb[i].dofpr_nargv; 904265Smws for (j = 0; j < pb[i].dofpr_nargc; j++) { 905265Smws mdb_printf("%s %s", "," + (j == 0), strtab + narg); 906265Smws narg += strlen(strtab + narg) + 1; 907265Smws } 908265Smws mdb_printf("\n"); 909265Smws mdb_printf("xargs:"); 910265Smws xarg = pb[i].dofpr_xargv; 911265Smws for (j = 0; j < pb[i].dofpr_xargc; j++) { 912265Smws mdb_printf("%s %s", "," + (j == 0), strtab + xarg); 913265Smws xarg += strlen(strtab + xarg) + 1; 914265Smws } 915265Smws mdb_printf("\n"); 916265Smws mdb_printf("map: "); 917265Smws for (j = 0; j < pb[i].dofpr_xargc; j++) { 918265Smws mdb_printf("%s %d->%d", "," + (j == 0), 919265Smws args[pb[i].dofpr_argidx + j], j); 920265Smws } 921265Smws 922265Smws (void) mdb_dec_indent(2); 923265Smws mdb_printf("\n}\n"); 924265Smws } 925265Smws 926265Smws (void) mdb_dec_indent(2); 927265Smws mdb_printf("}\n"); 928265Smws 929265Smws return (0); 930265Smws } 931265Smws 932265Smws static int 933265Smws dof_sect_prargs(uintptr_t addr, dof_sec_t *sec) 934265Smws { 935265Smws int i; 936265Smws uint8_t arg; 937265Smws 938265Smws for (i = 0; i < sec->dofs_size; i++) { 939265Smws if (mdb_vread(&arg, sizeof (arg), 940265Smws addr + sec->dofs_offset + i) != sizeof (arg)) { 941265Smws mdb_warn("failed to read argument"); 942265Smws return (1); 943265Smws } 944265Smws 945265Smws mdb_printf("%d ", arg); 946265Smws 947265Smws if (i % 20 == 19) 948265Smws mdb_printf("\n"); 949265Smws } 950265Smws 951265Smws mdb_printf("\n"); 952265Smws 953265Smws return (0); 954265Smws } 955265Smws 956265Smws /*ARGSUSED*/ 957265Smws static int 958265Smws dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 959265Smws { 960265Smws dof_hdr_t dofh; 961265Smws dof_sec_t *dofs; 962265Smws const char *name; 963265Smws int i; 964265Smws 965265Smws if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) { 966265Smws mdb_warn("failed to read DOF header"); 967265Smws return (DCMD_ERR); 968265Smws } 969265Smws 970265Smws dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum, 971265Smws UM_SLEEP | UM_GC); 972265Smws 973265Smws for (i = 0; i < dofh.dofh_secnum; i++) { 974265Smws if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff + 975265Smws addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) { 976265Smws mdb_warn("failed to read DOF sections"); 977265Smws return (DCMD_ERR); 978265Smws } 979265Smws } 980265Smws 981265Smws for (i = 0; i < dofh.dofh_secnum; i++) { 982265Smws mdb_printf("%lx Section %d: ", (ulong_t) 983265Smws (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i); 984265Smws 985265Smws if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL) 986265Smws mdb_printf("%s\n", name); 987265Smws else 988265Smws mdb_printf("%u\n", dofs[i].dofs_type); 989265Smws 990265Smws (void) mdb_inc_indent(2); 991265Smws switch (dofs[i].dofs_type) { 992265Smws case DOF_SECT_PROVIDER: 993265Smws (void) dof_sect_provider(addr, &dofs[i], dofs); 994265Smws break; 995265Smws case DOF_SECT_STRTAB: 996265Smws (void) dof_sect_strtab(addr, &dofs[i]); 997265Smws break; 998265Smws case DOF_SECT_PRARGS: 999265Smws (void) dof_sect_prargs(addr, &dofs[i]); 1000265Smws break; 1001265Smws } 1002265Smws (void) mdb_dec_indent(2); 1003265Smws 1004265Smws mdb_printf("\n"); 1005265Smws } 1006265Smws 1007265Smws return (DCMD_OK); 1008265Smws } 1009265Smws 1010265Smws static const mdb_dcmd_t common_dcmds[] = { 1011265Smws { "difinstr", ":", "disassemble a DIF instruction", difinstr }, 1012265Smws { "difo", ":", "print a DIF object", difo }, 1013265Smws { "dof_hdr", "?", "print a DOF header", dof_hdr }, 1014265Smws { "dof_sec", ":", "print a DOF section header", dof_sec }, 1015265Smws { "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc }, 1016265Smws { "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc }, 1017265Smws { "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc }, 1018265Smws { "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr }, 1019265Smws { "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc }, 1020265Smws { "dofdump", ":", "dump DOF", dofdump }, 1021265Smws { NULL } 1022265Smws }; 1023265Smws 1024265Smws static const mdb_walker_t common_walkers[] = { 1025265Smws { "dof_sec", "walk DOF section header table given header address", 1026265Smws dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini }, 1027265Smws { NULL } 1028265Smws }; 1029265Smws 1030265Smws static mdb_modinfo_t modinfo = { 1031265Smws MDB_API_VERSION, NULL, NULL 1032265Smws }; 1033265Smws 1034265Smws const mdb_modinfo_t * 1035265Smws _mdb_init(void) 1036265Smws { 1037265Smws uint_t d = 0, kd = 0, w = 0, kw = 0; 1038265Smws const mdb_walker_t *wp; 1039265Smws const mdb_dcmd_t *dp; 1040265Smws 1041265Smws for (dp = common_dcmds; dp->dc_name != NULL; dp++) 1042265Smws d++; /* count common dcmds */ 1043265Smws 1044265Smws for (wp = common_walkers; wp->walk_name != NULL; wp++) 1045265Smws w++; /* count common walkers */ 1046265Smws 1047265Smws #ifdef _KERNEL 1048265Smws for (dp = kernel_dcmds; dp->dc_name != NULL; dp++) 1049265Smws kd++; /* count kernel dcmds */ 1050265Smws 1051265Smws for (wp = kernel_walkers; wp->walk_name != NULL; wp++) 1052265Smws kw++; /* count common walkers */ 1053265Smws #endif 1054265Smws 1055265Smws modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP); 1056265Smws modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP); 1057265Smws 1058265Smws bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d); 1059265Smws bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w); 1060265Smws 1061265Smws #ifdef _KERNEL 1062265Smws bcopy(kernel_dcmds, (void *) 1063265Smws (modinfo.mi_dcmds + d), sizeof (*dp) * kd); 1064265Smws bcopy(kernel_walkers, (void *) 1065265Smws (modinfo.mi_walkers + w), sizeof (*wp) * kw); 1066265Smws #endif 1067265Smws return (&modinfo); 1068265Smws } 1069265Smws 1070265Smws void 1071265Smws _mdb_fini(void) 1072265Smws { 1073265Smws const mdb_walker_t *wp; 1074265Smws const mdb_dcmd_t *dp; 1075265Smws uint_t d = 0, w = 0; 1076265Smws 1077265Smws for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++) 1078265Smws d++; 1079265Smws 1080265Smws for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++) 1081265Smws w++; 1082265Smws 1083265Smws mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1)); 1084265Smws mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1)); 1085265Smws } 1086