11a7c1b72Smws /* 21a7c1b72Smws * CDDL HEADER START 31a7c1b72Smws * 41a7c1b72Smws * The contents of this file are subject to the terms of the 5*ac448965Sahl * Common Development and Distribution License (the "License"). 6*ac448965Sahl * You may not use this file except in compliance with the License. 71a7c1b72Smws * 81a7c1b72Smws * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91a7c1b72Smws * or http://www.opensolaris.org/os/licensing. 101a7c1b72Smws * See the License for the specific language governing permissions 111a7c1b72Smws * and limitations under the License. 121a7c1b72Smws * 131a7c1b72Smws * When distributing Covered Code, include this CDDL HEADER in each 141a7c1b72Smws * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151a7c1b72Smws * If applicable, add the following below this CDDL HEADER, with the 161a7c1b72Smws * fields enclosed by brackets "[]" replaced with your own identifying 171a7c1b72Smws * information: Portions Copyright [yyyy] [name of copyright owner] 181a7c1b72Smws * 191a7c1b72Smws * CDDL HEADER END 201a7c1b72Smws */ 21*ac448965Sahl 221a7c1b72Smws /* 23*ac448965Sahl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241a7c1b72Smws * Use is subject to license terms. 251a7c1b72Smws */ 261a7c1b72Smws 271a7c1b72Smws #pragma ident "%Z%%M% %I% %E% SMI" 281a7c1b72Smws 291a7c1b72Smws #include <mdb/mdb_modapi.h> 301a7c1b72Smws #include <dtrace.h> 311a7c1b72Smws 321a7c1b72Smws extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 331a7c1b72Smws extern const char *dof_sec_name(uint32_t); 341a7c1b72Smws 351a7c1b72Smws extern const mdb_walker_t kernel_walkers[]; 361a7c1b72Smws extern const mdb_dcmd_t kernel_dcmds[]; 371a7c1b72Smws 381a7c1b72Smws /*ARGSUSED*/ 391a7c1b72Smws static void 401a7c1b72Smws dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 411a7c1b72Smws { 421a7c1b72Smws mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name, 431a7c1b72Smws DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 441a7c1b72Smws } 451a7c1b72Smws 461a7c1b72Smws /*ARGSUSED*/ 471a7c1b72Smws static void 481a7c1b72Smws dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 491a7c1b72Smws { 501a7c1b72Smws mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr)); 511a7c1b72Smws } 521a7c1b72Smws 531a7c1b72Smws /*ARGSUSED*/ 541a7c1b72Smws static void 551a7c1b72Smws dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 561a7c1b72Smws { 571a7c1b72Smws mdb_printf("%-4s [%%r%u], %%r%u", name, 581a7c1b72Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 591a7c1b72Smws } 601a7c1b72Smws 611a7c1b72Smws /*ARGSUSED*/ 621a7c1b72Smws static void 631a7c1b72Smws dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 641a7c1b72Smws { 651a7c1b72Smws mdb_printf("%-4s %%r%u, [%%r%u]", name, 661a7c1b72Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 671a7c1b72Smws } 681a7c1b72Smws 691a7c1b72Smws /*ARGSUSED*/ 701a7c1b72Smws static void 711a7c1b72Smws dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 721a7c1b72Smws { 731a7c1b72Smws mdb_printf("%s", name); 741a7c1b72Smws } 751a7c1b72Smws 761a7c1b72Smws /*ARGSUSED*/ 771a7c1b72Smws static void 781a7c1b72Smws dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 791a7c1b72Smws { 801a7c1b72Smws mdb_printf("%-4s %%r%u, %%r%u", name, 811a7c1b72Smws DIF_INSTR_R1(instr), DIF_INSTR_RD(instr)); 821a7c1b72Smws } 831a7c1b72Smws 841a7c1b72Smws /*ARGSUSED*/ 851a7c1b72Smws static void 861a7c1b72Smws dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 871a7c1b72Smws { 881a7c1b72Smws mdb_printf("%-4s %%r%u, %%r%u", name, 891a7c1b72Smws DIF_INSTR_R1(instr), DIF_INSTR_R2(instr)); 901a7c1b72Smws } 911a7c1b72Smws 921a7c1b72Smws /*ARGSUSED*/ 931a7c1b72Smws static void 941a7c1b72Smws dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 951a7c1b72Smws { 961a7c1b72Smws mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr)); 971a7c1b72Smws } 981a7c1b72Smws 991a7c1b72Smws static const char * 1001a7c1b72Smws dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope) 1011a7c1b72Smws { 1021a7c1b72Smws dtrace_difv_t *dvp; 1031a7c1b72Smws size_t varsize; 1041a7c1b72Smws caddr_t addr = NULL, str; 1051a7c1b72Smws uint_t i; 1061a7c1b72Smws 1071a7c1b72Smws if (dp == NULL) 1081a7c1b72Smws return (NULL); 1091a7c1b72Smws 1101a7c1b72Smws varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 1111a7c1b72Smws dvp = mdb_alloc(varsize, UM_SLEEP); 1121a7c1b72Smws 1131a7c1b72Smws if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 1141a7c1b72Smws mdb_free(dvp, varsize); 1151a7c1b72Smws return ("<unreadable>"); 1161a7c1b72Smws } 1171a7c1b72Smws 1181a7c1b72Smws for (i = 0; i < dp->dtdo_varlen; i++) { 1191a7c1b72Smws if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) { 1201a7c1b72Smws if (dvp[i].dtdv_name < dp->dtdo_strlen) 1211a7c1b72Smws addr = dp->dtdo_strtab + dvp[i].dtdv_name; 1221a7c1b72Smws break; 1231a7c1b72Smws } 1241a7c1b72Smws } 1251a7c1b72Smws 1261a7c1b72Smws mdb_free(dvp, varsize); 1271a7c1b72Smws 1281a7c1b72Smws if (addr == NULL) 1291a7c1b72Smws return (NULL); 1301a7c1b72Smws 1311a7c1b72Smws str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC); 1321a7c1b72Smws 1331a7c1b72Smws for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) { 1341a7c1b72Smws if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1) 1351a7c1b72Smws return ("<unreadable>"); 1361a7c1b72Smws } 1371a7c1b72Smws 1381a7c1b72Smws return (str); 1391a7c1b72Smws } 1401a7c1b72Smws 1411a7c1b72Smws static uint_t 1421a7c1b72Smws dis_scope(const char *name) 1431a7c1b72Smws { 1441a7c1b72Smws switch (name[2]) { 1451a7c1b72Smws case 'l': return (DIFV_SCOPE_LOCAL); 1461a7c1b72Smws case 't': return (DIFV_SCOPE_THREAD); 1471a7c1b72Smws case 'g': return (DIFV_SCOPE_GLOBAL); 1481a7c1b72Smws default: return (-1u); 1491a7c1b72Smws } 1501a7c1b72Smws } 1511a7c1b72Smws 1521a7c1b72Smws static void 1531a7c1b72Smws dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 1541a7c1b72Smws { 1551a7c1b72Smws uint_t var = DIF_INSTR_R1(instr); 1561a7c1b72Smws const char *vname; 1571a7c1b72Smws 1581a7c1b72Smws mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name, 1591a7c1b72Smws var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr)); 1601a7c1b72Smws 1611a7c1b72Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 1621a7c1b72Smws mdb_printf("\t\t! %s", vname); 1631a7c1b72Smws } 1641a7c1b72Smws 1651a7c1b72Smws static void 1661a7c1b72Smws dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 1671a7c1b72Smws { 1681a7c1b72Smws uint_t var = DIF_INSTR_VAR(instr); 1691a7c1b72Smws const char *vname; 1701a7c1b72Smws 1711a7c1b72Smws mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr)); 1721a7c1b72Smws 1731a7c1b72Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 1741a7c1b72Smws mdb_printf("\t\t! %s", vname); 1751a7c1b72Smws } 1761a7c1b72Smws 1771a7c1b72Smws static void 1781a7c1b72Smws dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 1791a7c1b72Smws { 1801a7c1b72Smws uint_t var = DIF_INSTR_VAR(instr); 1811a7c1b72Smws const char *vname; 1821a7c1b72Smws 1831a7c1b72Smws mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var); 1841a7c1b72Smws 1851a7c1b72Smws if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL) 1861a7c1b72Smws mdb_printf("\t\t! %s", vname); 1871a7c1b72Smws } 1881a7c1b72Smws 1891a7c1b72Smws static void 1901a7c1b72Smws dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 1911a7c1b72Smws { 1921a7c1b72Smws uint_t intptr = DIF_INSTR_INTEGER(instr); 1931a7c1b72Smws 1941a7c1b72Smws mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name, 1951a7c1b72Smws intptr, DIF_INSTR_RD(instr)); 1961a7c1b72Smws 1971a7c1b72Smws if (dp != NULL && intptr < dp->dtdo_intlen) { 1981a7c1b72Smws uint64_t *ip = mdb_alloc(dp->dtdo_intlen * 1991a7c1b72Smws sizeof (uint64_t), UM_SLEEP | UM_GC); 2001a7c1b72Smws 2011a7c1b72Smws if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t), 2021a7c1b72Smws (uintptr_t)dp->dtdo_inttab) == -1) 2031a7c1b72Smws mdb_warn("failed to read data at %p", dp->dtdo_inttab); 2041a7c1b72Smws else 2051a7c1b72Smws mdb_printf("\t\t! 0x%llx", ip[intptr]); 2061a7c1b72Smws } 2071a7c1b72Smws } 2081a7c1b72Smws 2091a7c1b72Smws static void 2101a7c1b72Smws dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 2111a7c1b72Smws { 2121a7c1b72Smws uint_t strptr = DIF_INSTR_STRING(instr); 2131a7c1b72Smws 2141a7c1b72Smws mdb_printf("%-4s DIF_STRING[%u], %%r%u", name, 2151a7c1b72Smws strptr, DIF_INSTR_RD(instr)); 2161a7c1b72Smws 2171a7c1b72Smws if (dp != NULL && strptr < dp->dtdo_strlen) { 2181a7c1b72Smws char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 2191a7c1b72Smws 2201a7c1b72Smws if (mdb_vread(str, dp->dtdo_strlen, 2211a7c1b72Smws (uintptr_t)dp->dtdo_strtab) == -1) 2221a7c1b72Smws mdb_warn("failed to read data at %p", dp->dtdo_strtab); 2231a7c1b72Smws else 2241a7c1b72Smws mdb_printf("\t\t! \"%s\"", str + strptr); 2251a7c1b72Smws } 2261a7c1b72Smws } 2271a7c1b72Smws 2281a7c1b72Smws /*ARGSUSED*/ 2291a7c1b72Smws static void 2301a7c1b72Smws dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 2311a7c1b72Smws { 2321a7c1b72Smws mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr)); 2331a7c1b72Smws } 2341a7c1b72Smws 2351a7c1b72Smws /*ARGSUSED*/ 2361a7c1b72Smws static void 2371a7c1b72Smws dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 2381a7c1b72Smws { 2391a7c1b72Smws uint_t subr = DIF_INSTR_SUBR(instr); 2401a7c1b72Smws 2411a7c1b72Smws mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s", 2421a7c1b72Smws name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr)); 2431a7c1b72Smws } 2441a7c1b72Smws 2451a7c1b72Smws /*ARGSUSED*/ 2461a7c1b72Smws static void 2471a7c1b72Smws dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 2481a7c1b72Smws { 2491a7c1b72Smws static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" }; 2501a7c1b72Smws uint_t type = DIF_INSTR_TYPE(instr); 2511a7c1b72Smws 2521a7c1b72Smws mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u", 2531a7c1b72Smws name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr)); 2541a7c1b72Smws 2551a7c1b72Smws if (type < sizeof (tnames) / sizeof (tnames[0])) 256187eccf8Sbmc mdb_printf("\t\t! %s", tnames[type]); 2571a7c1b72Smws } 2581a7c1b72Smws 2591a7c1b72Smws /*ARGSUSED*/ 2601a7c1b72Smws static void 2611a7c1b72Smws dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr) 2621a7c1b72Smws { 2631a7c1b72Smws mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name, 2641a7c1b72Smws DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr)); 2651a7c1b72Smws } 2661a7c1b72Smws 2671a7c1b72Smws static char * 2681a7c1b72Smws dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len) 2691a7c1b72Smws { 2701a7c1b72Smws char kind[8]; 2711a7c1b72Smws 2721a7c1b72Smws switch (t->dtdt_kind) { 2731a7c1b72Smws case DIF_TYPE_CTF: 2741a7c1b72Smws (void) strcpy(kind, "D type"); 2751a7c1b72Smws break; 2761a7c1b72Smws case DIF_TYPE_STRING: 2771a7c1b72Smws (void) strcpy(kind, "string"); 2781a7c1b72Smws break; 2791a7c1b72Smws default: 2801a7c1b72Smws (void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind); 2811a7c1b72Smws } 2821a7c1b72Smws 2831a7c1b72Smws if (t->dtdt_flags & DIF_TF_BYREF) { 2841a7c1b72Smws (void) mdb_snprintf(buf, len, 2851a7c1b72Smws "%s by ref (size %lu)", 2861a7c1b72Smws kind, (ulong_t)t->dtdt_size); 2871a7c1b72Smws } else { 2881a7c1b72Smws (void) mdb_snprintf(buf, len, "%s (size %lu)", 2891a7c1b72Smws kind, (ulong_t)t->dtdt_size); 2901a7c1b72Smws } 2911a7c1b72Smws 2921a7c1b72Smws return (buf); 2931a7c1b72Smws } 2941a7c1b72Smws 2951a7c1b72Smws static int 2961a7c1b72Smws dis(uintptr_t addr, dtrace_difo_t *dp) 2971a7c1b72Smws { 2981a7c1b72Smws static const struct opent { 2991a7c1b72Smws const char *op_name; 3001a7c1b72Smws void (*op_func)(const dtrace_difo_t *, 3011a7c1b72Smws const char *, dif_instr_t); 3021a7c1b72Smws } optab[] = { 3031a7c1b72Smws { "(illegal opcode)", dis_str }, 3041a7c1b72Smws { "or", dis_log }, /* DIF_OP_OR */ 3051a7c1b72Smws { "xor", dis_log }, /* DIF_OP_XOR */ 3061a7c1b72Smws { "and", dis_log }, /* DIF_OP_AND */ 3071a7c1b72Smws { "sll", dis_log }, /* DIF_OP_SLL */ 3081a7c1b72Smws { "srl", dis_log }, /* DIF_OP_SRL */ 3091a7c1b72Smws { "sub", dis_log }, /* DIF_OP_SUB */ 3101a7c1b72Smws { "add", dis_log }, /* DIF_OP_ADD */ 3111a7c1b72Smws { "mul", dis_log }, /* DIF_OP_MUL */ 3121a7c1b72Smws { "sdiv", dis_log }, /* DIF_OP_SDIV */ 3131a7c1b72Smws { "udiv", dis_log }, /* DIF_OP_UDIV */ 3141a7c1b72Smws { "srem", dis_log }, /* DIF_OP_SREM */ 3151a7c1b72Smws { "urem", dis_log }, /* DIF_OP_UREM */ 3161a7c1b72Smws { "not", dis_r1rd }, /* DIF_OP_NOT */ 3171a7c1b72Smws { "mov", dis_r1rd }, /* DIF_OP_MOV */ 3181a7c1b72Smws { "cmp", dis_cmp }, /* DIF_OP_CMP */ 3191a7c1b72Smws { "tst", dis_tst }, /* DIF_OP_TST */ 3201a7c1b72Smws { "ba", dis_branch }, /* DIF_OP_BA */ 3211a7c1b72Smws { "be", dis_branch }, /* DIF_OP_BE */ 3221a7c1b72Smws { "bne", dis_branch }, /* DIF_OP_BNE */ 3231a7c1b72Smws { "bg", dis_branch }, /* DIF_OP_BG */ 3241a7c1b72Smws { "bgu", dis_branch }, /* DIF_OP_BGU */ 3251a7c1b72Smws { "bge", dis_branch }, /* DIF_OP_BGE */ 3261a7c1b72Smws { "bgeu", dis_branch }, /* DIF_OP_BGEU */ 3271a7c1b72Smws { "bl", dis_branch }, /* DIF_OP_BL */ 3281a7c1b72Smws { "blu", dis_branch }, /* DIF_OP_BLU */ 3291a7c1b72Smws { "ble", dis_branch }, /* DIF_OP_BLE */ 3301a7c1b72Smws { "bleu", dis_branch }, /* DIF_OP_BLEU */ 3311a7c1b72Smws { "ldsb", dis_load }, /* DIF_OP_LDSB */ 3321a7c1b72Smws { "ldsh", dis_load }, /* DIF_OP_LDSH */ 3331a7c1b72Smws { "ldsw", dis_load }, /* DIF_OP_LDSW */ 3341a7c1b72Smws { "ldub", dis_load }, /* DIF_OP_LDUB */ 3351a7c1b72Smws { "lduh", dis_load }, /* DIF_OP_LDUH */ 3361a7c1b72Smws { "lduw", dis_load }, /* DIF_OP_LDUW */ 3371a7c1b72Smws { "ldx", dis_load }, /* DIF_OP_LDX */ 3381a7c1b72Smws { "ret", dis_ret }, /* DIF_OP_RET */ 3391a7c1b72Smws { "nop", dis_str }, /* DIF_OP_NOP */ 3401a7c1b72Smws { "setx", dis_setx }, /* DIF_OP_SETX */ 3411a7c1b72Smws { "sets", dis_sets }, /* DIF_OP_SETS */ 3421a7c1b72Smws { "scmp", dis_cmp }, /* DIF_OP_SCMP */ 3431a7c1b72Smws { "ldga", dis_lda }, /* DIF_OP_LDGA */ 3441a7c1b72Smws { "ldgs", dis_ldv }, /* DIF_OP_LDGS */ 3451a7c1b72Smws { "stgs", dis_stv }, /* DIF_OP_STGS */ 3461a7c1b72Smws { "ldta", dis_lda }, /* DIF_OP_LDTA */ 3471a7c1b72Smws { "ldts", dis_ldv }, /* DIF_OP_LDTS */ 3481a7c1b72Smws { "stts", dis_stv }, /* DIF_OP_STTS */ 3491a7c1b72Smws { "sra", dis_log }, /* DIF_OP_SRA */ 3501a7c1b72Smws { "call", dis_call }, /* DIF_OP_CALL */ 3511a7c1b72Smws { "pushtr", dis_pushts }, /* DIF_OP_PUSHTR */ 3521a7c1b72Smws { "pushtv", dis_pushts }, /* DIF_OP_PUSHTV */ 3531a7c1b72Smws { "popts", dis_str }, /* DIF_OP_POPTS */ 3541a7c1b72Smws { "flushts", dis_str }, /* DIF_OP_FLUSHTS */ 3551a7c1b72Smws { "ldgaa", dis_ldv }, /* DIF_OP_LDGAA */ 3561a7c1b72Smws { "ldtaa", dis_ldv }, /* DIF_OP_LDTAA */ 3571a7c1b72Smws { "stgaa", dis_stv }, /* DIF_OP_STGAA */ 3581a7c1b72Smws { "sttaa", dis_stv }, /* DIF_OP_STTAA */ 3591a7c1b72Smws { "ldls", dis_ldv }, /* DIF_OP_LDLS */ 3601a7c1b72Smws { "stls", dis_stv }, /* DIF_OP_STLS */ 3611a7c1b72Smws { "allocs", dis_r1rd }, /* DIF_OP_ALLOCS */ 3621a7c1b72Smws { "copys", dis_log }, /* DIF_OP_COPYS */ 3631a7c1b72Smws { "stb", dis_store }, /* DIF_OP_STB */ 3641a7c1b72Smws { "sth", dis_store }, /* DIF_OP_STH */ 3651a7c1b72Smws { "stw", dis_store }, /* DIF_OP_STW */ 3661a7c1b72Smws { "stx", dis_store }, /* DIF_OP_STX */ 3671a7c1b72Smws { "uldsb", dis_load }, /* DIF_OP_ULDSB */ 3681a7c1b72Smws { "uldsh", dis_load }, /* DIF_OP_ULDSH */ 3691a7c1b72Smws { "uldsw", dis_load }, /* DIF_OP_ULDSW */ 3701a7c1b72Smws { "uldub", dis_load }, /* DIF_OP_ULDUB */ 3711a7c1b72Smws { "ulduh", dis_load }, /* DIF_OP_ULDUH */ 3721a7c1b72Smws { "ulduw", dis_load }, /* DIF_OP_ULDUW */ 3731a7c1b72Smws { "uldx", dis_load }, /* DIF_OP_ULDX */ 3741a7c1b72Smws { "rldsb", dis_load }, /* DIF_OP_RLDSB */ 3751a7c1b72Smws { "rldsh", dis_load }, /* DIF_OP_RLDSH */ 3761a7c1b72Smws { "rldsw", dis_load }, /* DIF_OP_RLDSW */ 3771a7c1b72Smws { "rldub", dis_load }, /* DIF_OP_RLDUB */ 3781a7c1b72Smws { "rlduh", dis_load }, /* DIF_OP_RLDUH */ 3791a7c1b72Smws { "rlduw", dis_load }, /* DIF_OP_RLDUW */ 3801a7c1b72Smws { "rldx", dis_load }, /* DIF_OP_RLDX */ 3811a7c1b72Smws { "xlate", dis_xlate }, /* DIF_OP_XLATE */ 3821a7c1b72Smws { "xlarg", dis_xlate }, /* DIF_OP_XLARG */ 3831a7c1b72Smws }; 3841a7c1b72Smws 3851a7c1b72Smws dif_instr_t instr, opcode; 3861a7c1b72Smws const struct opent *op; 3871a7c1b72Smws 3881a7c1b72Smws if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) { 3891a7c1b72Smws mdb_warn("failed to read DIF instruction at %p", addr); 3901a7c1b72Smws return (DCMD_ERR); 3911a7c1b72Smws } 3921a7c1b72Smws 3931a7c1b72Smws opcode = DIF_INSTR_OP(instr); 3941a7c1b72Smws 3951a7c1b72Smws if (opcode >= sizeof (optab) / sizeof (optab[0])) 3961a7c1b72Smws opcode = 0; /* force invalid opcode message */ 3971a7c1b72Smws 3981a7c1b72Smws op = &optab[opcode]; 399187eccf8Sbmc mdb_printf("%0?p %08x ", addr, instr); 4001a7c1b72Smws op->op_func(dp, op->op_name, instr); 4011a7c1b72Smws mdb_printf("\n"); 4021a7c1b72Smws mdb_set_dot(addr + sizeof (dif_instr_t)); 4031a7c1b72Smws 4041a7c1b72Smws return (DCMD_OK); 4051a7c1b72Smws } 4061a7c1b72Smws 4071a7c1b72Smws /*ARGSUSED*/ 4081a7c1b72Smws int 4091a7c1b72Smws difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 4101a7c1b72Smws { 4111a7c1b72Smws dtrace_difo_t difo, *dp = &difo; 4121a7c1b72Smws uintptr_t instr, limit; 4131a7c1b72Smws dtrace_difv_t *dvp; 4141a7c1b72Smws size_t varsize; 4151a7c1b72Smws ulong_t i; 4161a7c1b72Smws char type[64]; 4171a7c1b72Smws char *str; 4181a7c1b72Smws 4191a7c1b72Smws if (!(flags & DCMD_ADDRSPEC)) 4201a7c1b72Smws return (DCMD_USAGE); 4211a7c1b72Smws 4221a7c1b72Smws if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) { 4231a7c1b72Smws mdb_warn("couldn't read dtrace_difo_t at %p", addr); 4241a7c1b72Smws return (DCMD_ERR); 4251a7c1b72Smws } 4261a7c1b72Smws 4271a7c1b72Smws mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n", 4281a7c1b72Smws addr, dp->dtdo_refcnt); 429187eccf8Sbmc mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION"); 4301a7c1b72Smws 4311a7c1b72Smws mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf); 4321a7c1b72Smws limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t); 4331a7c1b72Smws 4341a7c1b72Smws while ((instr = mdb_get_dot()) < limit) 4351a7c1b72Smws dis(instr, dp); 4361a7c1b72Smws 4371a7c1b72Smws if (dp->dtdo_varlen != 0) { 4381a7c1b72Smws mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n", 4391a7c1b72Smws "NAME", "ID", "KND", "SCP", "FLAG", "TYPE"); 4401a7c1b72Smws } 4411a7c1b72Smws 4421a7c1b72Smws varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen; 4431a7c1b72Smws dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC); 4441a7c1b72Smws 4451a7c1b72Smws if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) { 4461a7c1b72Smws mdb_warn("couldn't read dtdo_vartab"); 4471a7c1b72Smws return (DCMD_ERR); 4481a7c1b72Smws } 4491a7c1b72Smws 4501a7c1b72Smws str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC); 4511a7c1b72Smws 4521a7c1b72Smws if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) { 4531a7c1b72Smws mdb_warn("couldn't read dtdo_strtab"); 4541a7c1b72Smws return (DCMD_ERR); 4551a7c1b72Smws } 4561a7c1b72Smws 4571a7c1b72Smws for (i = 0; i < dp->dtdo_varlen; i++) { 4581a7c1b72Smws dtrace_difv_t *v = &dvp[i]; 4591a7c1b72Smws char kind[4], scope[4], flags[16] = { 0 }; 4601a7c1b72Smws 4611a7c1b72Smws switch (v->dtdv_kind) { 4621a7c1b72Smws case DIFV_KIND_ARRAY: 4631a7c1b72Smws (void) strcpy(kind, "arr"); 4641a7c1b72Smws break; 4651a7c1b72Smws case DIFV_KIND_SCALAR: 4661a7c1b72Smws (void) strcpy(kind, "scl"); 4671a7c1b72Smws break; 4681a7c1b72Smws default: 4691a7c1b72Smws (void) mdb_snprintf(kind, sizeof (kind), 4701a7c1b72Smws "%u", v->dtdv_kind); 4711a7c1b72Smws } 4721a7c1b72Smws 4731a7c1b72Smws switch (v->dtdv_scope) { 4741a7c1b72Smws case DIFV_SCOPE_GLOBAL: 4751a7c1b72Smws (void) strcpy(scope, "glb"); 4761a7c1b72Smws break; 4771a7c1b72Smws case DIFV_SCOPE_THREAD: 4781a7c1b72Smws (void) strcpy(scope, "tls"); 4791a7c1b72Smws break; 4801a7c1b72Smws case DIFV_SCOPE_LOCAL: 4811a7c1b72Smws (void) strcpy(scope, "loc"); 4821a7c1b72Smws break; 4831a7c1b72Smws default: 4841a7c1b72Smws (void) mdb_snprintf(scope, sizeof (scope), 4851a7c1b72Smws "%u", v->dtdv_scope); 4861a7c1b72Smws } 4871a7c1b72Smws 4881a7c1b72Smws if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) { 4891a7c1b72Smws (void) mdb_snprintf(flags, sizeof (flags), "/0x%x", 4901a7c1b72Smws v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)); 4911a7c1b72Smws } 4921a7c1b72Smws 4931a7c1b72Smws if (v->dtdv_flags & DIFV_F_REF) 4941a7c1b72Smws (void) strcat(flags, "/r"); 4951a7c1b72Smws if (v->dtdv_flags & DIFV_F_MOD) 4961a7c1b72Smws (void) strcat(flags, "/w"); 4971a7c1b72Smws 4981a7c1b72Smws mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n", 4991a7c1b72Smws &str[v->dtdv_name], 5001a7c1b72Smws v->dtdv_id, kind, scope, flags + 1, 5011a7c1b72Smws dis_typestr(&v->dtdv_type, type, sizeof (type))); 5021a7c1b72Smws } 5031a7c1b72Smws 5041a7c1b72Smws mdb_printf("\n%<b>RETURN%</b>\n%s\n\n", 5051a7c1b72Smws dis_typestr(&dp->dtdo_rtype, type, sizeof (type))); 5061a7c1b72Smws 5071a7c1b72Smws return (DCMD_OK); 5081a7c1b72Smws } 5091a7c1b72Smws 5101a7c1b72Smws /*ARGSUSED*/ 5111a7c1b72Smws int 5121a7c1b72Smws difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5131a7c1b72Smws { 5141a7c1b72Smws if (!(flags & DCMD_ADDRSPEC)) 5151a7c1b72Smws return (DCMD_USAGE); 5161a7c1b72Smws 5171a7c1b72Smws return (dis(addr, NULL)); 5181a7c1b72Smws } 5191a7c1b72Smws 5201a7c1b72Smws /*ARGSUSED*/ 5211a7c1b72Smws int 5221a7c1b72Smws dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5231a7c1b72Smws { 5241a7c1b72Smws dof_hdr_t h; 5251a7c1b72Smws 5261a7c1b72Smws if (argc != 0) 5271a7c1b72Smws return (DCMD_USAGE); 5281a7c1b72Smws 5291a7c1b72Smws if (!(flags & DCMD_ADDRSPEC)) 5301a7c1b72Smws addr = 0; /* assume base of file in file target */ 5311a7c1b72Smws 5321a7c1b72Smws if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 5331a7c1b72Smws mdb_warn("failed to read header at %p", addr); 5341a7c1b72Smws return (DCMD_ERR); 5351a7c1b72Smws } 5361a7c1b72Smws 5371a7c1b72Smws mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n", 5381a7c1b72Smws h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1], 5391a7c1b72Smws h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]); 5401a7c1b72Smws 5411a7c1b72Smws switch (h.dofh_ident[DOF_ID_MODEL]) { 5421a7c1b72Smws case DOF_MODEL_ILP32: 5431a7c1b72Smws mdb_printf("dofh_ident.id_model = ILP32\n"); 5441a7c1b72Smws break; 5451a7c1b72Smws case DOF_MODEL_LP64: 5461a7c1b72Smws mdb_printf("dofh_ident.id_model = LP64\n"); 5471a7c1b72Smws break; 5481a7c1b72Smws default: 5491a7c1b72Smws mdb_printf("dofh_ident.id_model = 0x%x\n", 5501a7c1b72Smws h.dofh_ident[DOF_ID_MODEL]); 5511a7c1b72Smws } 5521a7c1b72Smws 5531a7c1b72Smws switch (h.dofh_ident[DOF_ID_ENCODING]) { 5541a7c1b72Smws case DOF_ENCODE_LSB: 5551a7c1b72Smws mdb_printf("dofh_ident.id_encoding = LSB\n"); 5561a7c1b72Smws break; 5571a7c1b72Smws case DOF_ENCODE_MSB: 5581a7c1b72Smws mdb_printf("dofh_ident.id_encoding = MSB\n"); 5591a7c1b72Smws break; 5601a7c1b72Smws default: 5611a7c1b72Smws mdb_printf("dofh_ident.id_encoding = 0x%x\n", 5621a7c1b72Smws h.dofh_ident[DOF_ID_ENCODING]); 5631a7c1b72Smws } 5641a7c1b72Smws 5651a7c1b72Smws mdb_printf("dofh_ident.id_version = %u\n", 5661a7c1b72Smws h.dofh_ident[DOF_ID_VERSION]); 5671a7c1b72Smws mdb_printf("dofh_ident.id_difvers = %u\n", 5681a7c1b72Smws h.dofh_ident[DOF_ID_DIFVERS]); 5691a7c1b72Smws mdb_printf("dofh_ident.id_difireg = %u\n", 5701a7c1b72Smws h.dofh_ident[DOF_ID_DIFIREG]); 5711a7c1b72Smws mdb_printf("dofh_ident.id_diftreg = %u\n", 5721a7c1b72Smws h.dofh_ident[DOF_ID_DIFTREG]); 5731a7c1b72Smws 5741a7c1b72Smws mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags); 5751a7c1b72Smws mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize); 5761a7c1b72Smws mdb_printf("dofh_secsize = %u\n", h.dofh_secsize); 5771a7c1b72Smws mdb_printf("dofh_secnum = %u\n", h.dofh_secnum); 5781a7c1b72Smws mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff); 5791a7c1b72Smws mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz); 5801a7c1b72Smws mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz); 5811a7c1b72Smws 5821a7c1b72Smws return (DCMD_OK); 5831a7c1b72Smws } 5841a7c1b72Smws 5851a7c1b72Smws /*ARGSUSED*/ 5861a7c1b72Smws static int 5871a7c1b72Smws dof_sec_walk(uintptr_t addr, void *ignored, int *sec) 5881a7c1b72Smws { 5891a7c1b72Smws mdb_printf("%3d ", (*sec)++); 5901a7c1b72Smws (void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 5911a7c1b72Smws return (WALK_NEXT); 5921a7c1b72Smws } 5931a7c1b72Smws 5941a7c1b72Smws /*ARGSUSED*/ 5951a7c1b72Smws int 5961a7c1b72Smws dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5971a7c1b72Smws { 5981a7c1b72Smws const char *name; 5991a7c1b72Smws dof_sec_t s; 6001a7c1b72Smws 6011a7c1b72Smws if (!(flags & DCMD_ADDRSPEC)) 6021a7c1b72Smws mdb_printf("%<u>%-3s ", "NDX"); 6031a7c1b72Smws 6041a7c1b72Smws if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 6051a7c1b72Smws mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 6061a7c1b72Smws "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET", 6071a7c1b72Smws "SIZE"); 6081a7c1b72Smws } 6091a7c1b72Smws 6101a7c1b72Smws if (!(flags & DCMD_ADDRSPEC)) { 6111a7c1b72Smws int sec = 0; 6121a7c1b72Smws 6131a7c1b72Smws if (mdb_walk("dof_sec", 6141a7c1b72Smws (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) { 6151a7c1b72Smws mdb_warn("failed to walk dof_sec"); 6161a7c1b72Smws return (DCMD_ERR); 6171a7c1b72Smws } 6181a7c1b72Smws return (DCMD_OK); 6191a7c1b72Smws } 6201a7c1b72Smws 6211a7c1b72Smws if (argc != 0) 6221a7c1b72Smws return (DCMD_USAGE); 6231a7c1b72Smws 6241a7c1b72Smws if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 6251a7c1b72Smws mdb_warn("failed to read section header at %p", addr); 6261a7c1b72Smws return (DCMD_ERR); 6271a7c1b72Smws } 6281a7c1b72Smws 6291a7c1b72Smws mdb_printf("%?p ", addr); 6301a7c1b72Smws 6311a7c1b72Smws if ((name = dof_sec_name(s.dofs_type)) != NULL) 6321a7c1b72Smws mdb_printf("%-10s ", name); 6331a7c1b72Smws else 6341a7c1b72Smws mdb_printf("%-10u ", s.dofs_type); 6351a7c1b72Smws 6361a7c1b72Smws mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align, 6371a7c1b72Smws s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size); 6381a7c1b72Smws 6391a7c1b72Smws return (DCMD_OK); 6401a7c1b72Smws } 6411a7c1b72Smws 6421a7c1b72Smws int 6431a7c1b72Smws dof_sec_walk_init(mdb_walk_state_t *wsp) 6441a7c1b72Smws { 6451a7c1b72Smws dof_hdr_t h, *hp; 6461a7c1b72Smws size_t size; 6471a7c1b72Smws 6481a7c1b72Smws if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 6491a7c1b72Smws mdb_warn("failed to read DOF header at %p", wsp->walk_addr); 6501a7c1b72Smws return (WALK_ERR); 6511a7c1b72Smws } 6521a7c1b72Smws 6531a7c1b72Smws size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum; 6541a7c1b72Smws hp = mdb_alloc(size, UM_SLEEP); 6551a7c1b72Smws 6561a7c1b72Smws if (mdb_vread(hp, size, wsp->walk_addr) != size) { 6571a7c1b72Smws mdb_warn("failed to read DOF sections at %p", wsp->walk_addr); 6581a7c1b72Smws mdb_free(hp, size); 6591a7c1b72Smws return (WALK_ERR); 6601a7c1b72Smws } 6611a7c1b72Smws 6621a7c1b72Smws wsp->walk_arg = (void *)0; 6631a7c1b72Smws wsp->walk_data = hp; 6641a7c1b72Smws 6651a7c1b72Smws return (WALK_NEXT); 6661a7c1b72Smws } 6671a7c1b72Smws 6681a7c1b72Smws int 6691a7c1b72Smws dof_sec_walk_step(mdb_walk_state_t *wsp) 6701a7c1b72Smws { 6711a7c1b72Smws uint_t i = (uintptr_t)wsp->walk_arg; 6721a7c1b72Smws size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i; 6731a7c1b72Smws dof_hdr_t *hp = wsp->walk_data; 6741a7c1b72Smws dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off); 6751a7c1b72Smws 6761a7c1b72Smws if (i >= hp->dofh_secnum) 6771a7c1b72Smws return (WALK_DONE); 6781a7c1b72Smws 6791a7c1b72Smws wsp->walk_arg = (void *)(uintptr_t)(i + 1); 6801a7c1b72Smws return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 6811a7c1b72Smws } 6821a7c1b72Smws 6831a7c1b72Smws void 6841a7c1b72Smws dof_sec_walk_fini(mdb_walk_state_t *wsp) 6851a7c1b72Smws { 6861a7c1b72Smws dof_hdr_t *hp = wsp->walk_data; 6871a7c1b72Smws mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum); 6881a7c1b72Smws } 6891a7c1b72Smws 6901a7c1b72Smws /*ARGSUSED*/ 6911a7c1b72Smws int 6921a7c1b72Smws dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 6931a7c1b72Smws { 6941a7c1b72Smws dof_ecbdesc_t e; 6951a7c1b72Smws 6961a7c1b72Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 6971a7c1b72Smws return (DCMD_USAGE); 6981a7c1b72Smws 6991a7c1b72Smws if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) { 7001a7c1b72Smws mdb_warn("failed to read ecbdesc at %p", addr); 7011a7c1b72Smws return (DCMD_ERR); 7021a7c1b72Smws } 7031a7c1b72Smws 7041a7c1b72Smws mdb_printf("dofe_probes = %d\n", e.dofe_probes); 7051a7c1b72Smws mdb_printf("dofe_actions = %d\n", e.dofe_actions); 7061a7c1b72Smws mdb_printf("dofe_pred = %d\n", e.dofe_pred); 7071a7c1b72Smws mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg); 7081a7c1b72Smws 7091a7c1b72Smws return (DCMD_OK); 7101a7c1b72Smws } 7111a7c1b72Smws 7121a7c1b72Smws /*ARGSUSED*/ 7131a7c1b72Smws int 7141a7c1b72Smws dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7151a7c1b72Smws { 7161a7c1b72Smws dof_probedesc_t p; 7171a7c1b72Smws 7181a7c1b72Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 7191a7c1b72Smws return (DCMD_USAGE); 7201a7c1b72Smws 7211a7c1b72Smws if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) { 7221a7c1b72Smws mdb_warn("failed to read probedesc at %p", addr); 7231a7c1b72Smws return (DCMD_ERR); 7241a7c1b72Smws } 7251a7c1b72Smws 7261a7c1b72Smws mdb_printf("dofp_strtab = %d\n", p.dofp_strtab); 7271a7c1b72Smws mdb_printf("dofp_provider = %u\n", p.dofp_provider); 7281a7c1b72Smws mdb_printf("dofp_mod = %u\n", p.dofp_mod); 7291a7c1b72Smws mdb_printf("dofp_func = %u\n", p.dofp_func); 7301a7c1b72Smws mdb_printf("dofp_name = %u\n", p.dofp_name); 7311a7c1b72Smws mdb_printf("dofp_id = %u\n", p.dofp_id); 7321a7c1b72Smws 7331a7c1b72Smws return (DCMD_OK); 7341a7c1b72Smws } 7351a7c1b72Smws 7361a7c1b72Smws /*ARGSUSED*/ 7371a7c1b72Smws int 7381a7c1b72Smws dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7391a7c1b72Smws { 7401a7c1b72Smws dof_actdesc_t a; 7411a7c1b72Smws 7421a7c1b72Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 7431a7c1b72Smws return (DCMD_USAGE); 7441a7c1b72Smws 7451a7c1b72Smws if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 7461a7c1b72Smws mdb_warn("failed to read actdesc at %p", addr); 7471a7c1b72Smws return (DCMD_ERR); 7481a7c1b72Smws } 7491a7c1b72Smws 7501a7c1b72Smws mdb_printf("dofa_difo = %d\n", a.dofa_difo); 7511a7c1b72Smws mdb_printf("dofa_strtab = %d\n", a.dofa_strtab); 7521a7c1b72Smws mdb_printf("dofa_kind = %u\n", a.dofa_kind); 7531a7c1b72Smws mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple); 7541a7c1b72Smws mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg); 7551a7c1b72Smws mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg); 7561a7c1b72Smws 7571a7c1b72Smws return (DCMD_OK); 7581a7c1b72Smws } 7591a7c1b72Smws 7601a7c1b72Smws /*ARGSUSED*/ 7611a7c1b72Smws int 7621a7c1b72Smws dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7631a7c1b72Smws { 7641a7c1b72Smws dof_relohdr_t r; 7651a7c1b72Smws 7661a7c1b72Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 7671a7c1b72Smws return (DCMD_USAGE); 7681a7c1b72Smws 7691a7c1b72Smws if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 7701a7c1b72Smws mdb_warn("failed to read relohdr at %p", addr); 7711a7c1b72Smws return (DCMD_ERR); 7721a7c1b72Smws } 7731a7c1b72Smws 7741a7c1b72Smws mdb_printf("dofr_strtab = %d\n", r.dofr_strtab); 7751a7c1b72Smws mdb_printf("dofr_relsec = %d\n", r.dofr_relsec); 7761a7c1b72Smws mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec); 7771a7c1b72Smws 7781a7c1b72Smws return (DCMD_OK); 7791a7c1b72Smws } 7801a7c1b72Smws 7811a7c1b72Smws /*ARGSUSED*/ 7821a7c1b72Smws int 7831a7c1b72Smws dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7841a7c1b72Smws { 7851a7c1b72Smws dof_relodesc_t r; 7861a7c1b72Smws 7871a7c1b72Smws if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 7881a7c1b72Smws return (DCMD_USAGE); 7891a7c1b72Smws 7901a7c1b72Smws if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) { 7911a7c1b72Smws mdb_warn("failed to read relodesc at %p", addr); 7921a7c1b72Smws return (DCMD_ERR); 7931a7c1b72Smws } 7941a7c1b72Smws 7951a7c1b72Smws mdb_printf("dofr_name = %u\n", r.dofr_name); 7961a7c1b72Smws mdb_printf("dofr_type = %u\n", r.dofr_type); 7971a7c1b72Smws mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset); 7981a7c1b72Smws mdb_printf("dofr_data = 0x%llx\n", r.dofr_data); 7991a7c1b72Smws 8001a7c1b72Smws return (DCMD_OK); 8011a7c1b72Smws } 8021a7c1b72Smws 8031a7c1b72Smws static int 8041a7c1b72Smws dof_sect_strtab(uintptr_t addr, dof_sec_t *sec) 8051a7c1b72Smws { 8061a7c1b72Smws char *strtab; 8071a7c1b72Smws size_t sz, i; 8081a7c1b72Smws 8091a7c1b72Smws sz = (size_t)sec->dofs_size; 8101a7c1b72Smws strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 8111a7c1b72Smws if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) { 8121a7c1b72Smws mdb_warn("failed to read string table"); 8131a7c1b72Smws return (1); 8141a7c1b72Smws } 8151a7c1b72Smws 8161a7c1b72Smws mdb_printf("size = %lx\n", sz); 8171a7c1b72Smws 8181a7c1b72Smws for (i = 0; i < sz; i++) { 8191a7c1b72Smws if (strtab[i] == '\0') 8201a7c1b72Smws mdb_printf("\\0"); 8211a7c1b72Smws else 8221a7c1b72Smws mdb_printf("%c", strtab[i]); 8231a7c1b72Smws } 8241a7c1b72Smws 8251a7c1b72Smws mdb_printf("\n"); 8261a7c1b72Smws 8271a7c1b72Smws return (0); 8281a7c1b72Smws } 8291a7c1b72Smws 8301a7c1b72Smws static int 831*ac448965Sahl dof_sect_provider(dof_hdr_t *dofh, uintptr_t addr, dof_sec_t *sec, 832*ac448965Sahl dof_sec_t *dofs) 8331a7c1b72Smws { 8341a7c1b72Smws dof_provider_t pv; 8351a7c1b72Smws dof_probe_t *pb; 836*ac448965Sahl char *strtab, *p; 837*ac448965Sahl uint32_t *offs, *enoffs; 8381a7c1b72Smws uint8_t *args = NULL; 8391a7c1b72Smws size_t sz; 8401a7c1b72Smws int i, j; 8411a7c1b72Smws dof_stridx_t narg, xarg; 8421a7c1b72Smws 843*ac448965Sahl sz = MIN(sec->dofs_size, sizeof (dof_provider_t)); 844*ac448965Sahl if (mdb_vread(&pv, sz, addr + sec->dofs_offset) != sz) { 8451a7c1b72Smws mdb_warn("failed to read DOF provider"); 8461a7c1b72Smws return (-1); 8471a7c1b72Smws } 8481a7c1b72Smws 8491a7c1b72Smws sz = dofs[pv.dofpv_strtab].dofs_size; 8501a7c1b72Smws strtab = mdb_alloc(sz, UM_SLEEP | UM_GC); 8511a7c1b72Smws if (mdb_vread(strtab, sz, addr + 8521a7c1b72Smws dofs[pv.dofpv_strtab].dofs_offset) != sz) { 8531a7c1b72Smws mdb_warn("failed to read string table"); 8541a7c1b72Smws return (-1); 8551a7c1b72Smws } 8561a7c1b72Smws 8571a7c1b72Smws mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset), 8581a7c1b72Smws strtab + pv.dofpv_name); 8591a7c1b72Smws 8601a7c1b72Smws sz = dofs[pv.dofpv_prargs].dofs_size; 8611a7c1b72Smws if (sz != 0) { 8621a7c1b72Smws args = mdb_alloc(sz, UM_SLEEP | UM_GC); 8631a7c1b72Smws if (mdb_vread(args, sz, addr + 8641a7c1b72Smws dofs[pv.dofpv_prargs].dofs_offset) != sz) { 8651a7c1b72Smws mdb_warn("failed to read args"); 8661a7c1b72Smws return (-1); 8671a7c1b72Smws } 8681a7c1b72Smws } 8691a7c1b72Smws 8701a7c1b72Smws sz = dofs[pv.dofpv_proffs].dofs_size; 8711a7c1b72Smws offs = mdb_alloc(sz, UM_SLEEP | UM_GC); 8721a7c1b72Smws if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset) 8731a7c1b72Smws != sz) { 874*ac448965Sahl mdb_warn("failed to read offsets"); 8751a7c1b72Smws return (-1); 8761a7c1b72Smws } 8771a7c1b72Smws 878*ac448965Sahl enoffs = NULL; 879*ac448965Sahl if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 || 880*ac448965Sahl pv.dofpv_prenoffs == 0) { 881*ac448965Sahl sz = dofs[pv.dofpv_prenoffs].dofs_size; 882*ac448965Sahl enoffs = mdb_alloc(sz, UM_SLEEP | UM_GC); 883*ac448965Sahl if (mdb_vread(enoffs, sz, addr + 884*ac448965Sahl dofs[pv.dofpv_prenoffs].dofs_offset) != sz) { 885*ac448965Sahl mdb_warn("failed to read is-enabled offsets"); 886*ac448965Sahl return (-1); 887*ac448965Sahl } 888*ac448965Sahl } 889*ac448965Sahl 8901a7c1b72Smws sz = dofs[pv.dofpv_probes].dofs_size; 891*ac448965Sahl p = mdb_alloc(sz, UM_SLEEP | UM_GC); 892*ac448965Sahl if (mdb_vread(p, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) { 8931a7c1b72Smws mdb_warn("failed to read probes"); 8941a7c1b72Smws return (-1); 8951a7c1b72Smws } 8961a7c1b72Smws 8971a7c1b72Smws (void) mdb_inc_indent(2); 8981a7c1b72Smws 8991a7c1b72Smws for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) { 900*ac448965Sahl pb = (dof_probe_t *)(uintptr_t)(p + 901*ac448965Sahl i * dofs[pv.dofpv_probes].dofs_entsize); 902*ac448965Sahl 9031a7c1b72Smws mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr + 9041a7c1b72Smws dofs[pv.dofpv_probes].dofs_offset + 9051a7c1b72Smws i * dofs[pv.dofpv_probes].dofs_entsize), 906*ac448965Sahl strtab + pb->dofpr_func, 907*ac448965Sahl strtab + pb->dofpr_name); 9081a7c1b72Smws 9091a7c1b72Smws (void) mdb_inc_indent(2); 910*ac448965Sahl mdb_printf("addr: %p\n", (ulong_t)pb->dofpr_addr); 9111a7c1b72Smws mdb_printf("offs: "); 912*ac448965Sahl for (j = 0; j < pb->dofpr_noffs; j++) { 9131a7c1b72Smws mdb_printf("%s %x", "," + (j == 0), 914*ac448965Sahl offs[pb->dofpr_offidx + j]); 9151a7c1b72Smws } 9161a7c1b72Smws mdb_printf("\n"); 9171a7c1b72Smws 918*ac448965Sahl if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) { 919*ac448965Sahl mdb_printf("enoffs: "); 920*ac448965Sahl if (enoffs == NULL) { 921*ac448965Sahl if (pb->dofpr_nenoffs != 0) 922*ac448965Sahl mdb_printf("<error>"); 923*ac448965Sahl } else { 924*ac448965Sahl for (j = 0; j < pb->dofpr_nenoffs; j++) { 925*ac448965Sahl mdb_printf("%s %x", "," + (j == 0), 926*ac448965Sahl enoffs[pb->dofpr_enoffidx + j]); 927*ac448965Sahl } 928*ac448965Sahl } 929*ac448965Sahl mdb_printf("\n"); 930*ac448965Sahl } 931*ac448965Sahl 9321a7c1b72Smws mdb_printf("nargs:"); 933*ac448965Sahl narg = pb->dofpr_nargv; 934*ac448965Sahl for (j = 0; j < pb->dofpr_nargc; j++) { 9351a7c1b72Smws mdb_printf("%s %s", "," + (j == 0), strtab + narg); 9361a7c1b72Smws narg += strlen(strtab + narg) + 1; 9371a7c1b72Smws } 9381a7c1b72Smws mdb_printf("\n"); 9391a7c1b72Smws mdb_printf("xargs:"); 940*ac448965Sahl xarg = pb->dofpr_xargv; 941*ac448965Sahl for (j = 0; j < pb->dofpr_xargc; j++) { 9421a7c1b72Smws mdb_printf("%s %s", "," + (j == 0), strtab + xarg); 9431a7c1b72Smws xarg += strlen(strtab + xarg) + 1; 9441a7c1b72Smws } 9451a7c1b72Smws mdb_printf("\n"); 9461a7c1b72Smws mdb_printf("map: "); 947*ac448965Sahl for (j = 0; j < pb->dofpr_xargc; j++) { 9481a7c1b72Smws mdb_printf("%s %d->%d", "," + (j == 0), 949*ac448965Sahl args[pb->dofpr_argidx + j], j); 9501a7c1b72Smws } 9511a7c1b72Smws 9521a7c1b72Smws (void) mdb_dec_indent(2); 9531a7c1b72Smws mdb_printf("\n}\n"); 9541a7c1b72Smws } 9551a7c1b72Smws 9561a7c1b72Smws (void) mdb_dec_indent(2); 9571a7c1b72Smws mdb_printf("}\n"); 9581a7c1b72Smws 9591a7c1b72Smws return (0); 9601a7c1b72Smws } 9611a7c1b72Smws 9621a7c1b72Smws static int 9631a7c1b72Smws dof_sect_prargs(uintptr_t addr, dof_sec_t *sec) 9641a7c1b72Smws { 9651a7c1b72Smws int i; 9661a7c1b72Smws uint8_t arg; 9671a7c1b72Smws 9681a7c1b72Smws for (i = 0; i < sec->dofs_size; i++) { 9691a7c1b72Smws if (mdb_vread(&arg, sizeof (arg), 9701a7c1b72Smws addr + sec->dofs_offset + i) != sizeof (arg)) { 9711a7c1b72Smws mdb_warn("failed to read argument"); 9721a7c1b72Smws return (1); 9731a7c1b72Smws } 9741a7c1b72Smws 9751a7c1b72Smws mdb_printf("%d ", arg); 9761a7c1b72Smws 9771a7c1b72Smws if (i % 20 == 19) 9781a7c1b72Smws mdb_printf("\n"); 9791a7c1b72Smws } 9801a7c1b72Smws 9811a7c1b72Smws mdb_printf("\n"); 9821a7c1b72Smws 9831a7c1b72Smws return (0); 9841a7c1b72Smws } 9851a7c1b72Smws 9861a7c1b72Smws /*ARGSUSED*/ 9871a7c1b72Smws static int 9881a7c1b72Smws dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 9891a7c1b72Smws { 9901a7c1b72Smws dof_hdr_t dofh; 9911a7c1b72Smws dof_sec_t *dofs; 9921a7c1b72Smws const char *name; 9931a7c1b72Smws int i; 9941a7c1b72Smws 9951a7c1b72Smws if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) { 9961a7c1b72Smws mdb_warn("failed to read DOF header"); 9971a7c1b72Smws return (DCMD_ERR); 9981a7c1b72Smws } 9991a7c1b72Smws 10001a7c1b72Smws dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum, 10011a7c1b72Smws UM_SLEEP | UM_GC); 10021a7c1b72Smws 10031a7c1b72Smws for (i = 0; i < dofh.dofh_secnum; i++) { 10041a7c1b72Smws if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff + 10051a7c1b72Smws addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) { 10061a7c1b72Smws mdb_warn("failed to read DOF sections"); 10071a7c1b72Smws return (DCMD_ERR); 10081a7c1b72Smws } 10091a7c1b72Smws } 10101a7c1b72Smws 10111a7c1b72Smws for (i = 0; i < dofh.dofh_secnum; i++) { 10121a7c1b72Smws mdb_printf("%lx Section %d: ", (ulong_t) 10131a7c1b72Smws (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i); 10141a7c1b72Smws 10151a7c1b72Smws if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL) 10161a7c1b72Smws mdb_printf("%s\n", name); 10171a7c1b72Smws else 10181a7c1b72Smws mdb_printf("%u\n", dofs[i].dofs_type); 10191a7c1b72Smws 10201a7c1b72Smws (void) mdb_inc_indent(2); 10211a7c1b72Smws switch (dofs[i].dofs_type) { 10221a7c1b72Smws case DOF_SECT_PROVIDER: 1023*ac448965Sahl (void) dof_sect_provider(&dofh, addr, &dofs[i], dofs); 10241a7c1b72Smws break; 10251a7c1b72Smws case DOF_SECT_STRTAB: 10261a7c1b72Smws (void) dof_sect_strtab(addr, &dofs[i]); 10271a7c1b72Smws break; 10281a7c1b72Smws case DOF_SECT_PRARGS: 10291a7c1b72Smws (void) dof_sect_prargs(addr, &dofs[i]); 10301a7c1b72Smws break; 10311a7c1b72Smws } 10321a7c1b72Smws (void) mdb_dec_indent(2); 10331a7c1b72Smws 10341a7c1b72Smws mdb_printf("\n"); 10351a7c1b72Smws } 10361a7c1b72Smws 10371a7c1b72Smws return (DCMD_OK); 10381a7c1b72Smws } 10391a7c1b72Smws 10401a7c1b72Smws static const mdb_dcmd_t common_dcmds[] = { 10411a7c1b72Smws { "difinstr", ":", "disassemble a DIF instruction", difinstr }, 10421a7c1b72Smws { "difo", ":", "print a DIF object", difo }, 10431a7c1b72Smws { "dof_hdr", "?", "print a DOF header", dof_hdr }, 10441a7c1b72Smws { "dof_sec", ":", "print a DOF section header", dof_sec }, 10451a7c1b72Smws { "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc }, 10461a7c1b72Smws { "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc }, 10471a7c1b72Smws { "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc }, 10481a7c1b72Smws { "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr }, 10491a7c1b72Smws { "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc }, 10501a7c1b72Smws { "dofdump", ":", "dump DOF", dofdump }, 10511a7c1b72Smws { NULL } 10521a7c1b72Smws }; 10531a7c1b72Smws 10541a7c1b72Smws static const mdb_walker_t common_walkers[] = { 10551a7c1b72Smws { "dof_sec", "walk DOF section header table given header address", 10561a7c1b72Smws dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini }, 10571a7c1b72Smws { NULL } 10581a7c1b72Smws }; 10591a7c1b72Smws 10601a7c1b72Smws static mdb_modinfo_t modinfo = { 10611a7c1b72Smws MDB_API_VERSION, NULL, NULL 10621a7c1b72Smws }; 10631a7c1b72Smws 10641a7c1b72Smws const mdb_modinfo_t * 10651a7c1b72Smws _mdb_init(void) 10661a7c1b72Smws { 10671a7c1b72Smws uint_t d = 0, kd = 0, w = 0, kw = 0; 10681a7c1b72Smws const mdb_walker_t *wp; 10691a7c1b72Smws const mdb_dcmd_t *dp; 10701a7c1b72Smws 10711a7c1b72Smws for (dp = common_dcmds; dp->dc_name != NULL; dp++) 10721a7c1b72Smws d++; /* count common dcmds */ 10731a7c1b72Smws 10741a7c1b72Smws for (wp = common_walkers; wp->walk_name != NULL; wp++) 10751a7c1b72Smws w++; /* count common walkers */ 10761a7c1b72Smws 10771a7c1b72Smws #ifdef _KERNEL 10781a7c1b72Smws for (dp = kernel_dcmds; dp->dc_name != NULL; dp++) 10791a7c1b72Smws kd++; /* count kernel dcmds */ 10801a7c1b72Smws 10811a7c1b72Smws for (wp = kernel_walkers; wp->walk_name != NULL; wp++) 10821a7c1b72Smws kw++; /* count common walkers */ 10831a7c1b72Smws #endif 10841a7c1b72Smws 10851a7c1b72Smws modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP); 10861a7c1b72Smws modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP); 10871a7c1b72Smws 10881a7c1b72Smws bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d); 10891a7c1b72Smws bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w); 10901a7c1b72Smws 10911a7c1b72Smws #ifdef _KERNEL 10921a7c1b72Smws bcopy(kernel_dcmds, (void *) 10931a7c1b72Smws (modinfo.mi_dcmds + d), sizeof (*dp) * kd); 10941a7c1b72Smws bcopy(kernel_walkers, (void *) 10951a7c1b72Smws (modinfo.mi_walkers + w), sizeof (*wp) * kw); 10961a7c1b72Smws #endif 10971a7c1b72Smws return (&modinfo); 10981a7c1b72Smws } 10991a7c1b72Smws 11001a7c1b72Smws void 11011a7c1b72Smws _mdb_fini(void) 11021a7c1b72Smws { 11031a7c1b72Smws const mdb_walker_t *wp; 11041a7c1b72Smws const mdb_dcmd_t *dp; 11051a7c1b72Smws uint_t d = 0, w = 0; 11061a7c1b72Smws 11071a7c1b72Smws for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++) 11081a7c1b72Smws d++; 11091a7c1b72Smws 11101a7c1b72Smws for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++) 11111a7c1b72Smws w++; 11121a7c1b72Smws 11131a7c1b72Smws mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1)); 11141a7c1b72Smws mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1)); 11151a7c1b72Smws } 1116