diff options
Diffstat (limited to 'usr/src/cmd')
74 files changed, 2179 insertions, 19 deletions
diff --git a/usr/src/cmd/mdb/Makefile.kmdb.files b/usr/src/cmd/mdb/Makefile.kmdb.files index 3c5983de21..a82206d42c 100644 --- a/usr/src/cmd/mdb/Makefile.kmdb.files +++ b/usr/src/cmd/mdb/Makefile.kmdb.files @@ -84,6 +84,7 @@ KMDBSRCS += \ mdb_target.c \ kmdb_terminfo.c \ mdb_termio.c \ + mdb_typedef.c \ mdb_umem.c \ kmdb_umemglue.c \ mdb_value.c \ diff --git a/usr/src/cmd/mdb/Makefile.libstandctf b/usr/src/cmd/mdb/Makefile.libstandctf index 7d4c8fbf0d..b5dce2d926 100644 --- a/usr/src/cmd/mdb/Makefile.libstandctf +++ b/usr/src/cmd/mdb/Makefile.libstandctf @@ -43,7 +43,7 @@ MAPFILE = ../../../common/libstandctf/mapfile $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -I$(SRC)/common/ctf -I../../../common -DCTF_OLD_VERSIONS -D_MDB \ - -Dvsnprintf=ctf_vsnprintf + -Dvsnprintf=ctf_vsnprintf -Dassfail=kmdb_prom_assfail # # kmdb is a kernel module, so we'll use the kernel's build flags. diff --git a/usr/src/cmd/mdb/Makefile.mdb b/usr/src/cmd/mdb/Makefile.mdb index f331a43fda..9d1d7b4d6c 100644 --- a/usr/src/cmd/mdb/Makefile.mdb +++ b/usr/src/cmd/mdb/Makefile.mdb @@ -85,6 +85,7 @@ SRCS += \ mdb_target.c \ mdb_tdb.c \ mdb_termio.c \ + mdb_typedef.c \ mdb_umem.c \ mdb_value.c \ mdb_vcb.c \ diff --git a/usr/src/cmd/mdb/common/libstandctf/mapfile b/usr/src/cmd/mdb/common/libstandctf/mapfile index e72c2ddbcf..63b2ec06ee 100644 --- a/usr/src/cmd/mdb/common/libstandctf/mapfile +++ b/usr/src/cmd/mdb/common/libstandctf/mapfile @@ -20,6 +20,9 @@ # # CDDL HEADER END # +# +# Copyright (c) 2012, Joyent, Inc. +# # # MAPFILE HEADER START @@ -40,15 +43,19 @@ $mapfile_version 2 SYMBOL_SCOPE { global: ctf_add_array; + ctf_add_float; + ctf_add_integer; ctf_add_member; ctf_add_pointer; ctf_add_struct; + ctf_add_type; ctf_add_typedef; ctf_add_union; ctf_array_info; ctf_bufopen; ctf_close; ctf_create; + ctf_delete_type; ctf_discard; ctf_enum_iter; ctf_enum_name; diff --git a/usr/src/cmd/mdb/common/mdb/mdb.c b/usr/src/cmd/mdb/common/mdb/mdb.c index 5c74c71772..5c1c5fc84a 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb.c +++ b/usr/src/cmd/mdb/common/mdb/mdb.c @@ -22,7 +22,6 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - /* * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2012 Joyent, Inc. All rights reserved. @@ -72,6 +71,7 @@ #include <mdb/mdb_err.h> #include <mdb/mdb_lex.h> #include <mdb/mdb_io.h> +#include <mdb/mdb_ctf.h> #ifdef _KMDB #include <kmdb/kmdb_module.h> #endif @@ -555,6 +555,13 @@ mdb_create(const char *execname, const char *arg0) (void) mdb_callb_add(NULL, MDB_CALLB_PROMPT, (mdb_callb_f)prompt_update, NULL); + /* + * The call to ctf_create that this does can in fact fail, but that's + * okay. All of the ctf functions that might use the synthetic types + * make sure that this is safe. + */ + (void) mdb_ctf_synthetics_init(); + #ifdef _KMDB (void) mdb_nv_create(&mdb.m_dmodctl, UM_SLEEP); #endif @@ -577,6 +584,8 @@ mdb_destroy(void) mdb_intr_disable(); + mdb_ctf_synthetics_fini(); + mdb_macalias_destroy(); /* @@ -899,6 +908,8 @@ mdb_call(uintmax_t addr, uintmax_t count, uint_t flags) flags | DCMD_PIPE_OUT, &cp->c_argv, &cp->c_addrv, cp->c_vcbs); + mdb.m_lastret = status; + ASSERT(mdb.m_in == iobs[MDB_IOB_RDIOB]); ASSERT(mdb.m_out == iobs[MDB_IOB_WRIOB]); } else { @@ -943,8 +954,8 @@ mdb_call(uintmax_t addr, uintmax_t count, uint_t flags) } else { mdb_intr_enable(); - (void) mdb_call_idcmd(cp->c_dcmd, addr, count, flags, - &cp->c_argv, &cp->c_addrv, cp->c_vcbs); + mdb.m_lastret = mdb_call_idcmd(cp->c_dcmd, addr, count, + flags, &cp->c_argv, &cp->c_addrv, cp->c_vcbs); mdb_intr_disable(); } diff --git a/usr/src/cmd/mdb/common/mdb/mdb.h b/usr/src/cmd/mdb/common/mdb/mdb.h index dc91906295..7f712ad340 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb.h +++ b/usr/src/cmd/mdb/common/mdb/mdb.h @@ -43,6 +43,7 @@ #include <mdb/mdb_modapi.h> #include <mdb/mdb_list.h> #include <mdb/mdb_vcb.h> +#include <mdb/mdb_ctf.h> #include <mdb/mdb_tab.h> #ifdef _KMDB #include <kmdb/kmdb_wr.h> @@ -181,6 +182,8 @@ typedef struct mdb { char **m_env; /* Current environment */ mdb_list_t m_cblist; /* List of callbacks */ mdb_nv_t m_macaliases; /* Name/value hash of ADB macro aliases */ + ctf_file_t *m_synth; /* Container for synthetic types */ + int m_lastret; /* Result of running the last command */ #ifdef _KMDB struct dpi_ops *m_dpi; /* DPI ops vector */ struct kdi *m_kdi; /* KDI ops vector */ diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c index 4a7b39fd57..add7845c68 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c @@ -26,7 +26,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Copyright (c) 2013 Joyent, Inc. All rights reserved. */ #include <sys/elf.h> @@ -67,6 +67,7 @@ #include <mdb/mdb_whatis_impl.h> #include <mdb/mdb_macalias.h> #include <mdb/mdb_tab.h> +#include <mdb/mdb_typedef.h> #ifdef _KMDB #include <kmdb/kmdb_kdi.h> #endif @@ -2978,6 +2979,8 @@ const mdb_dcmd_t mdb_dcmd_builtins[] = { { "status", NULL, "print summary of current target", cmd_notsup }, { "term", NULL, "display current terminal type", cmd_term }, { "typeset", "[+/-t] var ...", "set variable attributes", cmd_typeset }, + { "typedef", "[-c model | -d | -l | -r file ] [type] [name]", + "create synthetic types", cmd_typedef, cmd_typedef_help }, { "unset", "[name ...]", "unset variables", cmd_unset }, { "vars", "[-npt]", "print listing of variables", cmd_vars }, { "version", NULL, "print debugger version string", cmd_version }, diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c index 3181f8290c..3b545a08ff 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c @@ -24,6 +24,7 @@ */ /* * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <mdb/mdb_ctf.h> @@ -71,6 +72,125 @@ typedef struct mbr_info { mdb_ctf_id_t *mbr_typep; } mbr_info_t; +typedef struct synth_intrinsic { + const char *syn_name; + ctf_encoding_t syn_enc; + uint_t syn_kind; +} synth_intrinsic_t; + +typedef struct synth_typedef { + const char *syt_src; + const char *syt_targ; +} synth_typedef_t; + +/* + * As part of our support for synthetic types via ::typedef, we define a core + * set of types. + */ +static const synth_intrinsic_t synth_builtins32[] = { +{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER }, +{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER }, +{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER }, +{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER }, +{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "signed long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER }, +{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER }, +{ "unsigned long", { 0, 0, 32 }, CTF_K_INTEGER }, +{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER }, +{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER }, +{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT }, +{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT }, +{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT }, +{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT }, +{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT }, +{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT }, +{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT }, +{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT }, +{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT }, +{ NULL, { 0, 0, 0}, 0 } +}; + +static const synth_intrinsic_t synth_builtins64[] = { +{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER }, +{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER }, +{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER }, +{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER }, +{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER }, +{ "signed long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER }, +{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER }, +{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER }, +{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER }, +{ "unsigned long", { 0, 0, 64 }, CTF_K_INTEGER }, +{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER }, +{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER }, +{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT }, +{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT }, +{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT }, +{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT }, +{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT }, +{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT }, +{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT }, +{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT }, +{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT }, +{ NULL, { 0, 0, 0 }, 0 } +}; + +static const synth_typedef_t synth_typedefs32[] = { +{ "char", "int8_t" }, +{ "short", "int16_t" }, +{ "int", "int32_t" }, +{ "long long", "int64_t" }, +{ "int", "intptr_t" }, +{ "unsigned char", "uint8_t" }, +{ "unsigned short", "uint16_t" }, +{ "unsigned", "uint32_t" }, +{ "unsigned long long", "uint64_t" }, +{ "unsigned char", "uchar_t" }, +{ "unsigned short", "ushort_t" }, +{ "unsigned", "uint_t" }, +{ "unsigned long", "ulong_t" }, +{ "unsigned long long", "u_longlong_t" }, +{ "int", "ptrdiff_t" }, +{ "unsigned", "uintptr_t" }, +{ NULL, NULL } +}; + +static const synth_typedef_t synth_typedefs64[] = { +{ "char", "int8_t" }, +{ "short", "int16_t" }, +{ "int", "int32_t" }, +{ "long", "int64_t" }, +{ "long", "intptr_t" }, +{ "unsigned char", "uint8_t" }, +{ "unsigned short", "uint16_t" }, +{ "unsigned", "uint32_t" }, +{ "unsigned long", "uint64_t" }, +{ "unsigned char", "uchar_t" }, +{ "unsigned short", "ushort_t" }, +{ "unsigned", "uint_t" }, +{ "unsigned long", "ulong_t" }, +{ "unsigned long long", "u_longlong_t" }, +{ "long", "ptrdiff_t" }, +{ "unsigned long", "uintptr_t" }, +{ NULL, NULL } +}; + static void set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id) { @@ -146,6 +266,7 @@ name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp) /* * Attempt to look up the name in the primary object file. If this * fails and the name was unscoped, search all remaining object files. + * Finally, search the synthetic types. */ if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL || (id = ctf_lookup_by_name(fp, name)) == CTF_ERR || @@ -162,6 +283,10 @@ name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp) if (arg.tn_id != CTF_ERR) { fp = arg.tn_fp; id = arg.tn_id; + } else if (mdb.m_synth != NULL) { + if ((id = ctf_lookup_by_name(mdb.m_synth, + name)) != CTF_ERR) + fp = mdb.m_synth; } } @@ -675,7 +800,12 @@ mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) int ret; type_iter_t ti; - if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL) + if (object == MDB_CTF_SYNTHETIC_ITER) + fp = mdb.m_synth; + else + fp = mdb_tgt_name_to_ctf(t, object); + + if (fp == NULL) return (-1); ti.ti_cb = cb; @@ -1553,3 +1683,461 @@ mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va, return (ctf_bufopen(&ctdata, &symtab, &strtab, errp)); } + +int +mdb_ctf_synthetics_init(void) +{ + int err; + + if ((mdb.m_synth = ctf_create(&err)) == NULL) + return (set_errno(ctf_to_errno(err))); + + return (0); +} + +void +mdb_ctf_synthetics_fini(void) +{ + if (mdb.m_synth == NULL) + return; + + ctf_close(mdb.m_synth); + mdb.m_synth = NULL; +} + +int +mdb_ctf_synthetics_create_base(int kind) +{ + const synth_intrinsic_t *synp; + const synth_typedef_t *sytp; + int err; + ctf_id_t id; + ctf_file_t *cp = mdb.m_synth; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + switch (kind) { + case SYNTHETIC_ILP32: + synp = synth_builtins32; + sytp = synth_typedefs32; + break; + case SYNTHETIC_LP64: + synp = synth_builtins64; + sytp = synth_typedefs64; + break; + default: + mdb_dprintf(MDB_DBG_CTF, "invalid type of intrinsic: %d\n", + kind); + return (1); + } + + err = 0; + for (; synp->syn_name != NULL; synp++) { + if (synp->syn_kind == CTF_K_INTEGER) { + err = ctf_add_integer(cp, CTF_ADD_ROOT, synp->syn_name, + &synp->syn_enc); + } else { + err = ctf_add_float(cp, CTF_ADD_ROOT, synp->syn_name, + &synp->syn_enc); + } + + if (err == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "couldn't add synthetic " + "type: %s\n", synp->syn_name); + goto discard; + } + } + + if (ctf_update(cp) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n"); + goto discard; + } + + for (; sytp->syt_src != NULL; sytp++) { + id = ctf_lookup_by_name(cp, sytp->syt_src); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "cailed to lookup %s: %s\n", + sytp->syt_src, ctf_errmsg(ctf_errno(cp))); + goto discard; + } + if (ctf_add_typedef(cp, CTF_ADD_ROOT, sytp->syt_targ, id) == + CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "couldn't add typedef %s " + "%s: %s\n", sytp->syt_targ, sytp->syt_src, + ctf_errmsg(ctf_errno(cp))); + goto discard; + } + } + + if (ctf_update(cp) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n"); + goto discard; + } + + return (0); + +discard: + err = set_errno(ctf_to_errno(ctf_errno(cp))); + (void) ctf_discard(cp); + return (err); +} + +int +mdb_ctf_synthetics_reset(void) +{ + mdb_ctf_synthetics_fini(); + return (mdb_ctf_synthetics_init()); +} + +int +mdb_ctf_add_typedef(const char *name, const mdb_ctf_id_t *p, mdb_ctf_id_t *new) +{ + ctf_id_t rid; + mdb_ctf_id_t tid; + mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + if (mdb_ctf_lookup_by_name(name, &tid) == 0) { + mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type " + "with that name already exists\n", name); + return (set_errno(EEXIST)); + } + + rid = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id); + if (rid == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add reference type: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + rid = ctf_add_typedef(mdb.m_synth, CTF_ADD_ROOT, name, rid); + if (rid == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add typedef: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (new != NULL) + set_ctf_id(new, mdb.m_synth, rid); + + return (0); +} + +int +mdb_ctf_add_struct(const char *name, mdb_ctf_id_t *rid) +{ + mdb_ctf_id_t tid; + ctf_id_t id; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) { + mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type " + "with that name already exists\n", name); + return (set_errno(EEXIST)); + } + + if ((id = ctf_add_struct(mdb.m_synth, CTF_ADD_ROOT, name)) == + CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add struct: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (rid != NULL) + set_ctf_id(rid, mdb.m_synth, id); + + return (0); +} + +int +mdb_ctf_add_union(const char *name, mdb_ctf_id_t *rid) +{ + mdb_ctf_id_t tid; + ctf_id_t id; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) { + mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type " + "with that name already exists\n", name); + return (set_errno(EEXIST)); + } + + if ((id = ctf_add_union(mdb.m_synth, CTF_ADD_ROOT, name)) == + CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add union: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (rid != NULL) + set_ctf_id(rid, mdb.m_synth, id); + + return (0); +} + +int +mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name, + const mdb_ctf_id_t *mtype, mdb_ctf_id_t *rid) +{ + ctf_id_t id, mtid; + mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; + mdb_ctf_impl_t *mcim = (mdb_ctf_impl_t *)mtype; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (DCMD_ERR); + } + + if (mcip->mci_fp != mdb.m_synth) { + mdb_dprintf(MDB_DBG_CTF, "requested to add member to a type " + "that wasn't created from a synthetic\n"); + return (set_errno(EINVAL)); + } + + mtid = ctf_add_type(mdb.m_synth, mcim->mci_fp, mcim->mci_id); + if (mtid == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n", + name, ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (rid != NULL) + set_ctf_id(rid, mdb.m_synth, id); + + return (0); +} + +int +mdb_ctf_add_array(const mdb_ctf_arinfo_t *marp, mdb_ctf_id_t *rid) +{ + mdb_ctf_impl_t *mcip; + ctf_arinfo_t car; + ctf_id_t id; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + car.ctr_nelems = marp->mta_nelems; + + mcip = (mdb_ctf_impl_t *)&marp->mta_contents; + id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + car.ctr_contents = id; + + mcip = (mdb_ctf_impl_t *)&marp->mta_index; + id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + car.ctr_index = id; + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + id = ctf_add_array(mdb.m_synth, CTF_ADD_ROOT, &car); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (rid != NULL) + set_ctf_id(rid, mdb.m_synth, id); + + return (0); +} + +int +mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid) +{ + ctf_id_t id; + mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; + + if (mdb.m_synth == NULL) { + mdb_printf("synthetic types disabled: ctf create failed\n"); + return (1); + } + + id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add pointer type: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + + id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, id); + if (id == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + + if (rid != NULL) + set_ctf_id(rid, mdb.m_synth, id); + + return (0); +} + +int +mdb_ctf_type_delete(const mdb_ctf_id_t *id) +{ + int ret; + + mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)id; + + if (mcip->mci_fp != mdb.m_synth) { + mdb_warn("bad ctf_file_t, expected synth container\n"); + return (1); + } + + ret = ctf_delete_type(mcip->mci_fp, mcip->mci_id); + if (ret != 0) { + mdb_dprintf(MDB_DBG_CTF, "failed to delete synthetic type: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + if (ctf_update(mdb.m_synth) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s", + ctf_errmsg(ctf_errno(mdb.m_synth))); + return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth)))); + } + + return (0); +} + +static int +mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg) +{ + ctf_file_t *targ = arg; + mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)&id; + + if (ctf_add_type(targ, mcip->mci_fp, mcip->mci_id) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to add type %d: %s\n", + mcip->mci_id, ctf_errmsg(ctf_errno(mcip->mci_fp))); + return (set_errno(ctf_to_errno(ctf_errno(mcip->mci_fp)))); + } + + return (0); +} + +int +mdb_ctf_synthetics_from_file(const char *file) +{ + ctf_file_t *fp, *syn = mdb.m_synth; + int ret; + type_iter_t ti; + + if (syn == NULL) { + mdb_warn("synthetic types disabled: ctf create failed\n"); + return (1); + } + + if ((fp = mdb_ctf_open(file, &ret)) == NULL) { + mdb_warn("failed to parse ctf data in %s", file); + return (1); + } + + ret = DCMD_OK; + ti.ti_fp = fp; + ti.ti_arg = syn; + ti.ti_cb = mdb_ctf_synthetics_file_cb; + if (ctf_type_iter(fp, type_iter_cb, &ti) == CTF_ERR) { + ret = set_errno(ctf_to_errno(ctf_errno(fp))); + mdb_warn("failed to add types"); + goto cleanup; + } + + if (ctf_update(syn) == CTF_ERR) { + mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n"); + ret = set_errno(ctf_to_errno(ctf_errno(fp))); + } + +cleanup: + ctf_close(fp); + if (ret != 0) + (void) ctf_discard(syn); + return (ret); +} diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h index 05b56a381a..2396145299 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h @@ -24,6 +24,7 @@ */ /* * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #ifndef _MDB_CTF_H @@ -101,6 +102,29 @@ extern const char *mdb_ctf_enum_name(mdb_ctf_id_t, int); extern int mdb_ctf_member_iter(mdb_ctf_id_t, mdb_ctf_member_f *, void *); extern int mdb_ctf_enum_iter(mdb_ctf_id_t, mdb_ctf_enum_f *, void *); extern int mdb_ctf_type_iter(const char *, mdb_ctf_type_f *, void *); +extern int mdb_ctf_type_delete(const mdb_ctf_id_t *); + +/* + * Special values for mdb_ctf_type_iter. + */ +#define MDB_CTF_SYNTHETIC_ITER (const char *)(-1L) + +#define SYNTHETIC_ILP32 1 +#define SYNTHETIC_LP64 2 +extern int mdb_ctf_synthetics_create_base(int); +extern int mdb_ctf_synthetics_reset(void); + +/* + * Synthetic creation routines + */ +extern int mdb_ctf_add_typedef(const char *, const mdb_ctf_id_t *, + mdb_ctf_id_t *); +extern int mdb_ctf_add_struct(const char *, mdb_ctf_id_t *); +extern int mdb_ctf_add_union(const char *, mdb_ctf_id_t *); +extern int mdb_ctf_add_member(const mdb_ctf_id_t *, const char *, + const mdb_ctf_id_t *, mdb_ctf_id_t *); +extern int mdb_ctf_add_array(const mdb_ctf_arinfo_t *, mdb_ctf_id_t *); +extern int mdb_ctf_add_pointer(const mdb_ctf_id_t *, mdb_ctf_id_t *); /* utility stuff */ extern ctf_id_t mdb_ctf_type_id(mdb_ctf_id_t); @@ -128,6 +152,9 @@ extern ctf_file_t *mdb_ctf_open(const char *, int *); /* Internal */ extern ctf_file_t *mdb_ctf_bufopen(const void *, size_t, /* Internal */ const void *, Shdr *, const void *, Shdr *, int *); extern void mdb_ctf_close(ctf_file_t *fp); /* Internal */ +extern int mdb_ctf_synthetics_init(void); /* Internal */ +extern void mdb_ctf_synthetics_fini(void); /* Internal */ +extern int mdb_ctf_synthetics_from_file(const char *); /* Internal */ #endif diff --git a/usr/src/cmd/mdb/common/mdb/mdb_main.c b/usr/src/cmd/mdb/common/mdb/mdb_main.c index 41535f4643..90e048bb82 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_main.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_main.c @@ -323,10 +323,12 @@ usage(int status) { mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] " "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " - "[-R root] [-V dis-version] [object [core] | core | suffix]\n\n", + "[-R root] [-V dis-version] [-e expr] " + "[object [core] | core | suffix]\n\n", mdb.m_pname); mdb_iob_puts(mdb.m_err, + "\t-e evaluate expr and return status\n" "\t-f force raw file debugging mode\n" "\t-k force kernel debugging mode\n" "\t-m disable demand-loading of module symbols\n" @@ -420,6 +422,7 @@ main(int argc, char *argv[], char *envp[]) char *p; const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; + const char *eflag = NULL; int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; int ttylike; @@ -508,8 +511,15 @@ main(int argc, char *argv[], char *envp[]) while (optind < argc) { while ((c = getopt(argc, argv, - "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { + "e:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { switch (c) { + case 'e': + if (eflag != NULL) { + warn("-e already specified\n"); + terminate(2); + } + eflag = optarg; + break; case 'f': fflag++; tgt_ctor = mdb_rawfile_tgt_create; @@ -691,6 +701,12 @@ main(int argc, char *argv[], char *envp[]) /*NOTREACHED*/ } + if (eflag != NULL) { + IOP_CLOSE(in_io); + in_io = mdb_strio_create(eflag); + mdb.m_lastret = 0; + } + /* * If standard input appears to have tty attributes, attempt to * initialize a terminal i/o backend on top of stdin and stdout. @@ -1079,7 +1095,8 @@ tcreate: continue; } - terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1); + terminate((status == MDB_ERR_QUIT || status == 0) ? + (eflag != NULL && mdb.m_lastret != 0 ? 1 : 0) : 1); /*NOTREACHED*/ return (0); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_proc.c b/usr/src/cmd/mdb/common/mdb/mdb_proc.c index 1b7cdc544b..667bfe8c47 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_proc.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_proc.c @@ -4505,6 +4505,14 @@ pt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, */ if (PTL_GETREGS(t, tid, grs) == 0) { *rp = r | (ulong_t)grs[rd_num]; + if (rd_flags & MDB_TGT_R_32) + *rp &= 0xffffffffULL; + else if (rd_flags & MDB_TGT_R_16) + *rp &= 0xffffULL; + else if (rd_flags & MDB_TGT_R_8H) + *rp = (*rp & 0xff00ULL) >> 8; + else if (rd_flags & MDB_TGT_R_8L) + *rp &= 0xffULL; return (0); } return (-1); @@ -4531,6 +4539,16 @@ pt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r) ushort_t rd_flags = MDB_TGT_R_FLAGS(rd_nval); if (!MDB_TGT_R_IS_FP(rd_flags)) { + + if (rd_flags & MDB_TGT_R_32) + r &= 0xffffffffULL; + else if (rd_flags & MDB_TGT_R_16) + r &= 0xffffULL; + else if (rd_flags & MDB_TGT_R_8H) + r = (r & 0xffULL) << 8; + else if (rd_flags & MDB_TGT_R_8L) + r &= 0xffULL; + #if defined(__sparc) && defined(_ILP32) /* * If we are debugging on 32-bit SPARC, the globals and diff --git a/usr/src/cmd/mdb/common/mdb/mdb_tab.c b/usr/src/cmd/mdb/common/mdb/mdb_tab.c index b06b5db680..8b43ecdb12 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_tab.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_tab.c @@ -579,6 +579,8 @@ mdb_tab_complete_type(mdb_tab_cookie_t *mcp, const char *name, uint_t flags) mdb_tab_setmbase(mcp, name); (void) mdb_tgt_object_iter(t, mdb_tab_complete_module, mcp); + (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, tab_complete_type, + mcp); return (0); } diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target_impl.h b/usr/src/cmd/mdb/common/mdb/mdb_target_impl.h index ecc5331a1e..7f78bc4879 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_target_impl.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_target_impl.h @@ -22,12 +22,13 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_TARGET_IMPL_H #define _MDB_TARGET_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_target.h> #include <mdb/mdb_module.h> #include <mdb/mdb_list.h> @@ -250,6 +251,10 @@ extern long mdb_tgt_nop(); /* Return 0 for success */ #define MDB_TGT_R_FPQ 0x040 /* Quad-precision floating-point */ #define MDB_TGT_R_FPU 0x080 /* FPU control/status register */ #define MDB_TGT_R_RDONLY 0x100 /* Register is read-only */ +#define MDB_TGT_R_32 0x200 /* 32-bit version of register */ +#define MDB_TGT_R_16 0x400 /* 16-bit version of register */ +#define MDB_TGT_R_8H 0x800 /* upper half of a 16-bit reg */ +#define MDB_TGT_R_8L 0x1000 /* lower half of a 16-bit reg */ #define MDB_TGT_R_IS_FP(f) ((f) & 0xf0) /* Test MDB_TGT_R_FP* bits */ diff --git a/usr/src/cmd/mdb/common/mdb/mdb_typedef.c b/usr/src/cmd/mdb/common/mdb/mdb_typedef.c new file mode 100644 index 0000000000..be6411596c --- /dev/null +++ b/usr/src/cmd/mdb/common/mdb/mdb_typedef.c @@ -0,0 +1,773 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2013 Joyent, Inc. All rights reserved. + */ + +/* + * ::typedef exists to allow a user to create and import auxiliary CTF + * information for the currently running target. ::typedef is similar to the C + * typedef keyword. However, ::typedef has no illusions of grandeur. It is not a + * standards complaint version of C's typedef. For specifics on what it does and + * does not support, please see the help message for ::typedef later on in this + * file. + * + * In addition to allowing the user to create types, it has a notion of a + * built-in set of types that a compiler might provide. Currently ::typedef + * supports both the standard illumos 32-bit and 64-bit environments, mainly + * LP32 and LP64. These are not present by default; it is up to the user to + * request that they be inserted. + * + * To facilitate this, ::typedef adds all of its type information to an + * auxiliary CTF container that is a part of the global mdb state. This is + * abstracted away from ::typedef by the mdb_ctf_* apis. This container is + * referred to as the synthetic container, as it holds these synthetic types. + * The synthetic container does not have a parent CTF container. This is rather + * important to its operation, as a user can end up referencing types that come + * from many different such containers (eg. different kernel modules). As such, + * whenever a type is referenced that we do not know about, we search all of the + * CTF containers that mdb knows about it. If we find it, then that type is + * imported (along with all of its dependent types) into the synthetic + * container. + * + * Finally, ::typedef can source CTF information from external files with the -r + * option. This will copy in every type from their container into the synthetic + * container, because of this the parent and child relationship between + * containers with parents cannot be maintained. + */ + +#include <mdb/mdb_modapi.h> +#include <mdb/mdb_ctf.h> +#include <mdb/mdb_list.h> +#include <mdb/mdb_nv.h> + +struct parse_node; + +#define PN_F_POINTER 0x01 +#define PN_F_ARRAY 0x02 + +typedef struct parse_node { + mdb_list_t pn_list; /* list entry, must be first */ + char *pn_type; /* name of base type */ + char *pn_name; /* name of the member */ + int pn_flags; /* flags */ + int pn_nptrs; /* number of pointers */ + int pn_asub; /* value of array subscript */ +} parse_node_t; + +typedef struct parse_root { + mdb_list_t pr_nodes; /* list of members */ + int pr_kind; /* CTF_K_* */ + const char *pr_name; /* entity name */ + const char *pr_tname; /* entity typedef */ +} parse_root_t; + +static int +typedef_valid_identifier(const char *str) +{ + /* + * We can't use the standard ctype.h functions because those aren't + * necessairly available in kmdb. On the flip side, we only care about + * ascii characters here so that isn't too bad. + * + * C Identifiers have to start with a letter or a _. Afterwards they can + * be alphanumeric or an _. + */ + + if (*str == '\0') + return (1); + + if (*str != '_' && + (*str < 'A' || *str > 'Z') && + (*str < 'a' || *str > 'z')) + return (1); + str++; + + while (*str != '\0') { + if (*str != '_' && + (*str < '0' || *str > '9') && + (*str < 'A' || *str > 'Z') && + (*str < 'a' || *str > 'z')) + return (1); + str++; + } + + return (0); +} + +/*ARGSUSED*/ +static int +typedef_list_cb(mdb_ctf_id_t id, void *arg) +{ + char buf[MDB_SYM_NAMLEN]; + + /* + * The user may have created an anonymous structure or union as part of + * running ::typedef. If this is the case, we passed a NULL pointer for + * the name into the ctf routines. When we go back and ask for the name + * of that, ctf goes through and loops through all the declarations. + * This, however correctly, gives us back something undesirable to the + * user, eg. the name is simply 'struct' and 'union'. Because a typedef + * will always have a non-anonymous name for that, we instead opt to + * not include these anonymous names. ctf usefully includes a space as + * part of that name. + */ + (void) mdb_ctf_type_name(id, buf, sizeof (buf)); + if (strcmp("struct ", buf) != 0 && strcmp("union ", buf) != 0) + mdb_printf("%s\n", buf); + return (0); +} + +static char * +typedef_join_strings(int nstr, const mdb_arg_t *args, int flags) +{ + int i, size = 0; + char *ret, *sptr; + + for (i = 0; i <= nstr; i++) { + /* Always account for the space or the null terminator */ + size += strlen(args[i].a_un.a_str) + 1; + } + ret = mdb_alloc(sizeof (char) * size, flags); + if (ret == NULL) + return (NULL); + sptr = ret; + for (i = 0; i <= nstr; i++) { + (void) strcpy(sptr, args[i].a_un.a_str); + sptr += strlen(args[i].a_un.a_str); + *sptr = ' '; + sptr++; + } + *sptr = '\0'; + + return (ret); +} + +static int +typedef_list(void) +{ + (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, typedef_list_cb, + NULL); + return (DCMD_OK); +} + +static int +typedef_destroy(void) +{ + if (mdb_ctf_synthetics_reset() != 0) { + mdb_warn("failed to reset synthetic types"); + return (DCMD_ERR); + } + return (DCMD_OK); +} + +/* + * We've been asked to create the basic types that exist. We accept the + * following strings to indicate what we should create. + * - LP32, ILP32 (case insensitive) + * - LP64 + */ +static int +typedef_create(const char *arg) +{ + int kind; + + if (strcasecmp(arg, "LP32") == 0 || strcasecmp(arg, "ILP32") == 0) { + kind = SYNTHETIC_ILP32; + } else if (strcasecmp(arg, "LP64") == 0) { + kind = SYNTHETIC_LP64; + } else { + mdb_printf("invalid data model: %s\n", arg); + return (DCMD_USAGE); + } + + if (mdb_ctf_synthetics_create_base(kind) != 0) { + mdb_printf("failed to create intrinsic types, maybe " + "they already exist\n"); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +/* + * Search the current arguments for a complete member declaration. This function + * modifies the value of defn based on what's necessary for parsing. It returns + * the appropriate parse node in pnp. + */ +static int +typedef_parse_member(char *defn, char **next, parse_node_t **pnp) +{ + char *c, *name, *array; + int nptrs = 0; + parse_node_t *pn; + + c = strchr(defn, ';'); + if (c == NULL) { + mdb_printf("Cannot find semi-colon to delineate the end " + "of a member.\n"); + return (DCMD_ERR); + } + *c = '\0'; + *next = c + 1; + + c = strrchr(defn, ' '); + if (c == NULL) { + mdb_printf("Missing both a name and a type declaration for " + "a member. Instead, found '%s'\n", defn); + return (DCMD_ERR); + } + *c = '\0'; + name = c + 1; + c--; + while (*c == '*' || *c == ' ') { + if (*c == '*') + nptrs++; + c--; + } + *(c + 1) = '\0'; + + pn = mdb_zalloc(sizeof (parse_node_t), UM_SLEEP | UM_GC); + pn->pn_type = defn; + + /* + * Go through and prepare the name field. Note that we still have to + * check if this is a pointer or an array. We also need to strip the + * ending semi-colon. + */ + while (*name == '*') { + name++; + nptrs++; + } + + if ((c = strchr(name, '[')) != NULL) { + array = c; + if ((c = strchr(array, ']')) == NULL) { + mdb_printf("Found the beginning of an array size " + "but no closing ']' in %s\n", array); + return (DCMD_ERR); + } + *array = '\0'; + array++; + *c = '\0'; + pn->pn_flags |= PN_F_ARRAY; + pn->pn_asub = mdb_strtoull(array); + if (pn->pn_asub < 0) { + mdb_printf("Array lengths cannot be negative\n"); + return (DCMD_ERR); + } + } + + if (typedef_valid_identifier(name) != 0) { + mdb_printf("The name %s is not a valid C identifier.\n", + name); + return (DCMD_ERR); + } + + if (nptrs) { + pn->pn_flags |= PN_F_POINTER; + pn->pn_nptrs = nptrs; + } + pn->pn_name = name; + + *pnp = pn; + return (DCMD_OK); +} + +/* + * We're going to parse out our types here. Note that we are not strictly + * speaking a truely ANSI C compliant parser. Currently we support normal + * declarations except for the following: + * o function pointers + * o bit-fields + */ +static int +typedef_parse(char *defn, const char *name, parse_root_t **prp) +{ + int len, ret; + const char *kind, *basename; + char *c, *brace; + parse_root_t *pr; + parse_node_t *pn; + mdb_ctf_id_t id; + + pr = mdb_zalloc(sizeof (parse_root_t), UM_SLEEP | UM_GC); + basename = defn; + + c = strchr(defn, ' '); + if (c == NULL) { + mdb_printf("Invalid structure definition. Structure " + "must start with either 'struct {' or 'union {'\n"); + return (DCMD_ERR); + } + *c = '\0'; + + if (strcmp(defn, "struct") == 0) + pr->pr_kind = CTF_K_STRUCT; + else if (strcmp(defn, "union") == 0) + pr->pr_kind = CTF_K_UNION; + else { + mdb_printf("Invalid start of definition. " + "Expected 'struct' or 'union'. " + "Found: '%s'\n", defn); + return (DCMD_ERR); + } + + /* + * We transform this back to a space so we can validate that a + * non-anonymous struct or union name is valid. + */ + *c = ' '; + + kind = defn; + defn = c + 1; + while (*defn == ' ') + defn++; + + /* Check whether this is anonymous or not */ + if (*defn != '{') { + brace = strchr(defn, '{'); + c = brace; + if (c == NULL) { + mdb_printf("Missing opening brace for %s definition. " + "Expected '{'. " + "Found: '%c'\n", kind, *defn); + return (DCMD_ERR); + } + *c = '\0'; + c--; + while (*c == ' ') + c--; + *(c+1) = '\0'; + if (typedef_valid_identifier(defn) != 0) { + mdb_printf("The name %s is not a valid C identifier.\n", + defn); + return (DCMD_ERR); + } + + if (mdb_ctf_lookup_by_name(basename, &id) != CTF_ERR) { + mdb_printf("type name %s already in use\n", basename); + return (DCMD_ERR); + } + + pr->pr_name = defn; + defn = brace; + } else { + pr->pr_name = NULL; + } + + defn++; + while (*defn == ' ') + defn++; + + len = strlen(defn); + if (defn[len-1] != '}') { + mdb_printf("Missing closing brace for %s declaration. " + "Expected '}'.\n"); + return (DCMD_ERR); + } + defn[len-1] = '\0'; + + /* + * Start walking all the arguments, looking for a terminating semicolon + * for type definitions. + */ + for (;;) { + ret = typedef_parse_member(defn, &c, &pn); + if (ret == DCMD_ERR) + return (DCMD_ERR); + + mdb_list_append(&pr->pr_nodes, pn); + + while (*c == ' ') + c++; + + if (*c == '\0') + break; + + defn = c; + } + + pr->pr_tname = name; + *prp = pr; + + return (DCMD_OK); +} + +/* + * Make sure that none of the member names overlap and that the type names don't + * already exist. If we have an array entry that is a VLA, make sure it is the + * last member and not the only member. + */ +static int +typedef_validate(parse_root_t *pr) +{ + mdb_nv_t nv; + parse_node_t *pn; + mdb_ctf_id_t id; + int count = 0; + + (void) mdb_nv_create(&nv, UM_SLEEP | UM_GC); + for (pn = mdb_list_next(&pr->pr_nodes); pn != NULL; + pn = mdb_list_next(pn)) { + count++; + if (mdb_nv_lookup(&nv, pn->pn_name) != NULL) { + mdb_printf("duplicate name detected: %s\n", + pn->pn_name); + return (DCMD_ERR); + } + + /* + * Our parse tree won't go away before the nv, so it's simpler + * to just mark everything external. + */ + (void) mdb_nv_insert(&nv, pn->pn_name, NULL, 0, MDB_NV_EXTNAME); + + if (pn->pn_flags & PN_F_ARRAY && pn->pn_asub == 0) { + if (pr->pr_kind != CTF_K_STRUCT) { + mdb_printf("Flexible array members are only " + "valid in structs.\n"); + return (DCMD_ERR); + } + + if (&pn->pn_list != pr->pr_nodes.ml_prev) { + mdb_printf("Flexible array entries are only " + "allowed to be the last entry in a " + "struct\n"); + return (DCMD_ERR); + } + + if (count == 1) { + mdb_printf("Structs must have members aside " + "from a flexible member\n"); + return (DCMD_ERR); + } + } + } + + if (mdb_ctf_lookup_by_name(pr->pr_tname, &id) != CTF_ERR) { + mdb_printf("typedef name %s already exists\n", pr->pr_tname); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +static int +typedef_add(parse_root_t *pr) +{ + parse_node_t *pn; + mdb_ctf_id_t id, aid, tid, pid; + mdb_ctf_arinfo_t ar; + int ii; + + /* Pre-flight checks */ + if (typedef_validate(pr) == DCMD_ERR) + return (DCMD_ERR); + + if (pr->pr_kind == CTF_K_STRUCT) { + if (mdb_ctf_add_struct(pr->pr_name, &id) != 0) { + mdb_printf("failed to create struct for %s\n", + pr->pr_tname); + return (DCMD_ERR); + } + } else { + if (mdb_ctf_add_union(pr->pr_name, &id) != 0) { + mdb_printf("failed to create union for %s\n", + pr->pr_tname); + return (DCMD_ERR); + } + } + + for (pn = mdb_list_next(&pr->pr_nodes); pn != NULL; + pn = mdb_list_next(pn)) { + + if (mdb_ctf_lookup_by_name(pn->pn_type, &tid) == CTF_ERR) { + mdb_printf("failed to add member %s: type %s does " + "not exist\n", pn->pn_name, pn->pn_type); + goto destroy; + } + + if (pn->pn_flags & PN_F_POINTER) { + for (ii = 0; ii < pn->pn_nptrs; ii++) { + if (mdb_ctf_add_pointer(&tid, + &pid) != 0) { + mdb_printf("failed to add a pointer " + "type as part of member: %s\n", + pn->pn_name); + goto destroy; + } + tid = pid; + } + } + + if (pn->pn_flags & PN_F_ARRAY) { + if (mdb_ctf_lookup_by_name("long", &aid) != 0) { + mdb_printf("failed to lookup the type 'long' " + "for array indexes, are you running mdb " + "without a target or using ::typedef -c?"); + goto destroy; + } + + ar.mta_contents = tid; + ar.mta_index = aid; + ar.mta_nelems = pn->pn_asub; + + if (mdb_ctf_add_array(&ar, &tid) != 0) { + mdb_printf("failed to create array type for " + "memeber%s\n", pn->pn_name); + goto destroy; + } + } + + if (mdb_ctf_add_member(&id, pn->pn_name, &tid, NULL) == + CTF_ERR) { + mdb_printf("failed to create member %s\n", + pn->pn_name); + goto destroy; + } + } + + if (mdb_ctf_add_typedef(pr->pr_tname, &id, NULL) != 0) { + mdb_printf("failed to add typedef for %s\n", + pr->pr_tname); + goto destroy; + } + + return (DCMD_OK); + +destroy: + return (mdb_ctf_type_delete(&id)); +} + +static int +typedef_readfile(const char *file) +{ + int ret; + + ret = mdb_ctf_synthetics_from_file(file); + if (ret != DCMD_OK) + mdb_warn("failed to create synthetics from file\n"); + return (ret); +} + +/* ARGSUSED */ +int +cmd_typedef(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + mdb_ctf_id_t id; + int i; + int destroy = 0, list = 0; + const char *cmode = NULL, *rfile = NULL; + const char *dst, *src; + char *dup; + parse_root_t *pr; + + if (flags & DCMD_ADDRSPEC) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, + 'd', MDB_OPT_SETBITS, TRUE, &destroy, + 'l', MDB_OPT_SETBITS, TRUE, &list, + 'c', MDB_OPT_STR, &cmode, + 'r', MDB_OPT_STR, &rfile, NULL); + + argc -= i; + argv += i; + + /* + * All our options are mutually exclusive currently. + */ + i = 0; + if (destroy) + i++; + if (cmode != NULL) + i++; + if (list) + i++; + if (rfile != NULL) + i++; + if (i > 1) + return (DCMD_USAGE); + + if ((destroy || cmode != NULL || list || rfile != NULL) && argc != 0) + return (DCMD_USAGE); + + if (destroy) + return (typedef_destroy()); + + if (cmode) + return (typedef_create(cmode)); + + if (list) + return (typedef_list()); + + if (rfile) + return (typedef_readfile(rfile)); + + if (argc < 2) + return (DCMD_USAGE); + + /* + * Check to see if we are defining a struct or union. Note that we have + * to distinguish between struct foo and struct {. All typedef structs + * are annonymous structs that are only known by their typedef name. The + * same is true with unions. The problem that we have to deal with is + * that the ';' character in mdb causes mdb to begin another command. To + * work around that fact we require users to put the whole struct + * definition in a pair of "" or ''. + */ + if (argc == 2 && strchr(argv[0].a_un.a_str, '{') != NULL) { + dup = mdb_alloc(strlen(argv[0].a_un.a_str) + 1, + UM_GC | UM_SLEEP); + (void) strcpy(dup, argv[0].a_un.a_str); + if (typedef_parse(dup, argv[1].a_un.a_str, &pr) == DCMD_ERR) + return (DCMD_ERR); + if (typedef_add(pr) == DCMD_ERR) + return (DCMD_ERR); + + return (DCMD_OK); + } + + /* + * Someone could give us something like struct foobar or unsigned int or + * even long double imaginary. In this case we end up conjoining all + * arguments except the last one into one large string that we look up. + */ + if (argc - 1 == 1) { + src = argv[0].a_un.a_str; + } else { + src = typedef_join_strings(argc - 2, argv, UM_GC | UM_SLEEP); + } + + dst = argv[argc-1].a_un.a_str; + + if (mdb_ctf_lookup_by_name(dst, &id) != -1) { + mdb_printf("%s already exists\n", dst); + return (DCMD_ERR); + } + + if (mdb_ctf_lookup_by_name(src, &id) != 0) { + mdb_printf("%s does not exist\n", src); + return (DCMD_ERR); + } + + if (mdb_ctf_add_typedef(dst, &id, NULL) != 0) { + mdb_printf("failed to create typedef\n"); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +static char typedef_desc[] = +"::typedef operates like the C typedef keyword and creates a synthetic type\n" +"that is usable across mdb just like a type that is embedded in CTF data.\n" +"This includes familiar dcmds like ::print as well as mdb's tab completion\n" +"engine. The \"type\" argument can either be a named structure or union\n" +"declaration, like \"struct proc { int p_id; }\" declartion, an anonymous\n" +"structure or union declaration, like \"struct { int count; }\", or simply\n" +"the name of an existing type, like \"uint64_t\". Either form may refer to\n" +"other types already defined in CTF or a previous ::typedef invocation. When\n" +"debugging binaries without CTF, definitions for intrinsic types may be\n" +"created using the -c option. See the OPTIONS section for more information.\n" +"If a named struct or union is used, then a type will be created for it just\n" +"like in C. This may be used to mimic a forward declaration and an example of\n" +"this is in the EXAMPLES section. Regardless of whether a struct or union is\n" +"anonymous or named, the \"name\" argument is always required.\n" +"\n" +"When declaring anonymous structures and unions, the entire definition must\n" +"be enclosed within \"\" or ''. The ';' is used by mdb to separate commands\n" +"in a similar fashion to the shell. The ';' cannot be escaped, therefore\n" +"quoting your argument is necessary. See the EXAMPLES sections for examples\n" +"of what this looks like.\n" +"\n" +"All member and type names must be valid C identifiers. They must start with\n" +"an underscore or a letter. Subsequent characters are allowed to be letters,\n" +"numbers, or an underscore.\n" +"\n" +"Declaring arrays and any number of pointers in anonymous structures is \n" +"supported. However the following C features are not supported: \n" +" o function pointers (use a void * instead)\n" +" o bitfields (use an integer of the appropriate size instead)\n" +" o packed structures (all structures currently use their natural alignment)\n" +"\n" +"::typedef also allows you to read type definitions from a file. Definitions\n" +"can be read from any ELF file that has a CTF section that libctf can parse.\n" +"You can check if a file has such a section with elfdump(1). If a binary or\n" +"core dump does not have any type information, but you do have it elsewhere,\n" +"then you can use ::typedef -r to read in that type information.\n" +"\n"; + +static char typedef_opts[] = +" -c model create intrinsic types based on the specified data model.\n" +" The INTRINSICS section lists the built-in types and typedefs.\n" +" The following data models are supported:\n" +" o LP64 - Traditional illumos 64-bit program\n" +" o LP32 - Traditional illumos 32-bit program.\n" +" o ILP32 - An alternate name for LP32.\n" +" -d delete all synthetic types\n" +" -l list all synthetic types\n" +" -r file import type definitions (CTF) from another ELF file\n" +"\n"; + +static char typedef_examps[] = +" ::typedef -c LP64\n" +" ::typedef uint64_t bender_t\n" +" ::typedef struct proc new_proc_t\n" +" ::typedef \"union { int frodo; char sam; long gandalf; }\" ringbearer_t;\n" +" ::typedef \"struct { uintptr_t stone[7]; void **white; }\" gift_t\n" +" ::typedef \"struct list { struct list *l_next; struct list *l_prev; }\" " +"list_t\n" +" ::typedef -r /var/tmp/qemu-system-x86_64\n" +"\n"; + +static char typedef_intrins[] = +"The following C types and <stdint.h> typedefs are provided when \n" +"::typedef -c is used\n" +"\n" +" signed unsigned void\n" +" char short int\n" +" long long long signed char\n" +" signed short signed int signed long\n" +" singed long long unsigned char unsigned short\n" +" unsigned int unsigned long unsigned long long\n" +" _Bool float double\n" +" long double float imaginary double imaginary\n" +" long double imaginary float complex\n" +" double complex long double complex\n" +"\n" +" int8_t int16_t int32_t\n" +" int64_t intptr_t uint8_t\n" +" uint16_t uint32_t uint64_t\n" +" uchar_t ushort_t uint_t\n" +" ulong_t u_longlong_t ptrdiff_t\n" +" uintptr_t\n" +"\n"; + +void +cmd_typedef_help(void) +{ + mdb_printf("%s", typedef_desc); + (void) mdb_dec_indent(2); + mdb_printf("%<b>OPTIONS%</b>\n"); + (void) mdb_inc_indent(2); + mdb_printf("%s", typedef_opts); + (void) mdb_dec_indent(2); + mdb_printf("%<b>EXAMPLES%</b>\n"); + (void) mdb_inc_indent(2); + mdb_printf("%s", typedef_examps); + (void) mdb_dec_indent(2); + mdb_printf("%<b>INTRINSICS%</b>\n"); + (void) mdb_inc_indent(2); + mdb_printf("%s", typedef_intrins); +} diff --git a/usr/src/cmd/mdb/common/mdb/mdb_typedef.h b/usr/src/cmd/mdb/common/mdb/mdb_typedef.h new file mode 100644 index 0000000000..25721f8b9f --- /dev/null +++ b/usr/src/cmd/mdb/common/mdb/mdb_typedef.h @@ -0,0 +1,32 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + +#ifndef _MDB_TYPEDEF_H +#define _MDB_TYPEDEF_H + +#include <mdb/mdb_modapi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int cmd_typedef(uintptr_t, uint_t, int, const mdb_arg_t *); +void cmd_typedef_help(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _MDB_TYPEDEF_H */ diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c b/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c index 84db05c117..db04cb7a31 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c @@ -22,8 +22,9 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ /* * Libkvm Kernel Target Intel component @@ -57,6 +58,14 @@ kt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { if (strcmp(rname, rdp->rd_name) == 0) { *rp = kt->k_regs->kregs[rdp->rd_num]; + if (rdp->rd_flags & MDB_TGT_R_32) + *rp &= 0xffffffffULL; + else if (rdp->rd_flags & MDB_TGT_R_16) + *rp &= 0xffffULL; + else if (rdp->rd_flags & MDB_TGT_R_8H) + *rp = (*rp & 0xff00ULL) >> 8; + else if (rdp->rd_flags & MDB_TGT_R_8L) + *rp &= 0xffULL; return (0); } } @@ -75,6 +84,15 @@ kt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r) for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { if (strcmp(rname, rdp->rd_name) == 0) { + if (rdp->rd_flags & MDB_TGT_R_32) + r &= 0xffffffffULL; + else if (rdp->rd_flags & MDB_TGT_R_16) + r &= 0xffffULL; + else if (rdp->rd_flags & MDB_TGT_R_8H) + r = (r & 0xffULL) << 8; + else if (rdp->rd_flags & MDB_TGT_R_8L) + r &= 0xffULL; + kt->k_regs->kregs[rdp->rd_num] = (kreg_t)r; return (0); } diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c index c1bb17104f..432f22210c 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c @@ -25,6 +25,7 @@ */ /* * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -53,20 +54,69 @@ const mdb_tgt_regdesc_t mdb_amd64_kregs[] = { { "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT }, { "savpc", KREG_SAVPC, MDB_TGT_R_EXPORT }, { "rdi", KREG_RDI, MDB_TGT_R_EXPORT }, + { "edi", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "di", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dil", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rsi", KREG_RSI, MDB_TGT_R_EXPORT }, + { "esi", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "si", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "sil", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rdx", KREG_RDX, MDB_TGT_R_EXPORT }, + { "edx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "dx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rcx", KREG_RCX, MDB_TGT_R_EXPORT }, + { "ecx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "cx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r8", KREG_R8, MDB_TGT_R_EXPORT }, + { "r8d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r8w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r8l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r9", KREG_R9, MDB_TGT_R_EXPORT }, + { "r9d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r9w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r9l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rax", KREG_RAX, MDB_TGT_R_EXPORT }, + { "eax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "ax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rbx", KREG_RBX, MDB_TGT_R_EXPORT }, + { "ebx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rbp", KREG_RBP, MDB_TGT_R_EXPORT }, + { "ebp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bpl", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r10", KREG_R10, MDB_TGT_R_EXPORT }, + { "r10d", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r10w", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r10l", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r11", KREG_R11, MDB_TGT_R_EXPORT }, + { "r11d", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r11w", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r11l", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r12", KREG_R12, MDB_TGT_R_EXPORT }, + { "r12d", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r12w", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r12l", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r13", KREG_R13, MDB_TGT_R_EXPORT }, + { "r13d", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r13w", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r13l", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r14", KREG_R14, MDB_TGT_R_EXPORT }, + { "r14d", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r14w", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r14l", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r15", KREG_R15, MDB_TGT_R_EXPORT }, + { "r15d", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r15w", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r15l", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ds", KREG_DS, MDB_TGT_R_EXPORT }, { "es", KREG_ES, MDB_TGT_R_EXPORT }, { "fs", KREG_FS, MDB_TGT_R_EXPORT }, @@ -76,7 +126,11 @@ const mdb_tgt_regdesc_t mdb_amd64_kregs[] = { { "rip", KREG_RIP, MDB_TGT_R_EXPORT }, { "cs", KREG_CS, MDB_TGT_R_EXPORT }, { "rflags", KREG_RFLAGS, MDB_TGT_R_EXPORT }, + { "eflags", KREG_RFLAGS, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, { "rsp", KREG_RSP, MDB_TGT_R_EXPORT }, + { "esp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "sp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "spl", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ss", KREG_SS, MDB_TGT_R_EXPORT }, { NULL, 0, 0 } }; diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c index addb37e19f..43db94741b 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c @@ -22,8 +22,9 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #include <sys/types.h> #include <sys/reg.h> @@ -48,13 +49,29 @@ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT }, { "savpc", KREG_SAVPC, MDB_TGT_R_EXPORT }, { "eax", KREG_EAX, MDB_TGT_R_EXPORT }, + { "ax", KREG_EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", KREG_EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", KREG_EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ebx", KREG_EBX, MDB_TGT_R_EXPORT }, + { "bx", KREG_EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", KREG_EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", KREG_EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ecx", KREG_ECX, MDB_TGT_R_EXPORT }, + { "cx", KREG_ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", KREG_ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", KREG_ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "edx", KREG_EDX, MDB_TGT_R_EXPORT }, + { "dx", KREG_EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", KREG_EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", KREG_EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "esi", KREG_ESI, MDB_TGT_R_EXPORT }, + { "si", KREG_ESI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "edi", KREG_EDI, MDB_TGT_R_EXPORT }, + { "di", EDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "ebp", KREG_EBP, MDB_TGT_R_EXPORT }, + { "bp", KREG_EBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "esp", KREG_ESP, MDB_TGT_R_EXPORT }, + { "sp", KREG_ESP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "cs", KREG_CS, MDB_TGT_R_EXPORT }, { "ds", KREG_DS, MDB_TGT_R_EXPORT }, { "ss", KREG_SS, MDB_TGT_R_EXPORT }, @@ -64,6 +81,7 @@ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "eflags", KREG_EFLAGS, MDB_TGT_R_EXPORT }, { "eip", KREG_EIP, MDB_TGT_R_EXPORT }, { "uesp", KREG_UESP, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, + { "usp", KREG_UESP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "trapno", KREG_TRAPNO, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, { "err", KREG_ERR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, { NULL, 0, 0 } diff --git a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c index 29dd1682d1..75dd430c7d 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c @@ -23,8 +23,9 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ /* * User Process Target Intel 32-bit component @@ -46,26 +47,79 @@ const mdb_tgt_regdesc_t pt_regdesc[] = { { "r15", REG_R15, MDB_TGT_R_EXPORT }, + { "r15d", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r15w", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r15l", REG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r14", REG_R14, MDB_TGT_R_EXPORT }, + { "r14d", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r14w", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r14l", REG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r13", REG_R13, MDB_TGT_R_EXPORT }, + { "r13d", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r13w", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r13l", REG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r12", REG_R12, MDB_TGT_R_EXPORT }, + { "r12d", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r12w", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r12l", REG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r11", REG_R11, MDB_TGT_R_EXPORT }, + { "r11d", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r11w", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r11l", REG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r10", REG_R10, MDB_TGT_R_EXPORT }, + { "r10d", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r10w", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r10l", REG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r9", REG_R9, MDB_TGT_R_EXPORT }, + { "r9d", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r9w", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r9l", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "r8", REG_R8, MDB_TGT_R_EXPORT }, + { "r8d", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r8w", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r8l", REG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rdi", REG_RDI, MDB_TGT_R_EXPORT }, + { "edi", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "di", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dil", REG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rsi", REG_RSI, MDB_TGT_R_EXPORT }, + { "esi", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "si", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "sil", REG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rbp", REG_RBP, MDB_TGT_R_EXPORT }, + { "ebp", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bp", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bpl", REG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rbx", REG_RBX, MDB_TGT_R_EXPORT }, + { "ebx", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bx", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", REG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rdx", REG_RDX, MDB_TGT_R_EXPORT }, + { "edx", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "dx", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", REG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rcx", REG_RCX, MDB_TGT_R_EXPORT }, + { "ecx", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "cx", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", REG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "rax", REG_RAX, MDB_TGT_R_EXPORT }, + { "eax", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "ax", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", REG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "trapno", REG_TRAPNO, MDB_TGT_R_EXPORT }, { "err", REG_ERR, MDB_TGT_R_EXPORT }, { "rip", REG_RIP, MDB_TGT_R_EXPORT }, { "cs", REG_CS, MDB_TGT_R_EXPORT }, { "rflags", REG_RFL, MDB_TGT_R_EXPORT }, + { "eflags", REG_RFL, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, { "rsp", REG_RSP, MDB_TGT_R_EXPORT }, + { "esp", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "sp", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "spl", REG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ss", REG_SS, MDB_TGT_R_EXPORT }, { "fs", REG_FS, MDB_TGT_R_EXPORT }, { "gs", REG_GS, MDB_TGT_R_EXPORT }, diff --git a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c index bca8445d86..b532dc9149 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c @@ -23,8 +23,9 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ /* * User Process Target Intel 32-bit component @@ -50,19 +51,36 @@ const mdb_tgt_regdesc_t pt_regdesc[] = { { "es", ES, MDB_TGT_R_EXPORT }, { "ds", DS, MDB_TGT_R_EXPORT }, { "edi", EDI, MDB_TGT_R_EXPORT }, + { "di", EDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "esi", ESI, MDB_TGT_R_EXPORT }, + { "si", ESI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "ebp", EBP, MDB_TGT_R_EXPORT }, + { "bp", EBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "kesp", ESP, MDB_TGT_R_EXPORT }, + { "ksp", ESP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "ebx", EBX, MDB_TGT_R_EXPORT }, + { "bx", EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", EBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "edx", EDX, MDB_TGT_R_EXPORT }, + { "dx", EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", EDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "ecx", ECX, MDB_TGT_R_EXPORT }, + { "cx", ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", ECX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "eax", EAX, MDB_TGT_R_EXPORT }, + { "ax", EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", EAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, { "trapno", TRAPNO, MDB_TGT_R_EXPORT }, { "err", ERR, MDB_TGT_R_EXPORT }, { "eip", EIP, MDB_TGT_R_EXPORT }, { "cs", CS, MDB_TGT_R_EXPORT }, { "eflags", EFL, MDB_TGT_R_EXPORT }, { "esp", UESP, MDB_TGT_R_EXPORT }, + { "sp", UESP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, { "ss", SS, MDB_TGT_R_EXPORT }, { NULL, 0, 0 } }; diff --git a/usr/src/cmd/mdb/test/README b/usr/src/cmd/mdb/test/README new file mode 100644 index 0000000000..28127e5916 --- /dev/null +++ b/usr/src/cmd/mdb/test/README @@ -0,0 +1,18 @@ +MDB Test suite + +This provides a primordial version of a test suite for mdb. To run the tests, +run mtest. Tests exist in various subdirectories. The name of the test is +important. + +A test must start with either: + + o tst - Indicating that it should exit zero + o err - Indicating that it should exit non-zero + +A test must end with either: + + o mdb - Indicating that the file should be passed as standard input to mdb + o ksh - Indicating that it should be run with ksh + +A test may have an optional .out file which if present indicates that the test +should pass if and only if its standard ouput matches its standar error. diff --git a/usr/src/cmd/mdb/test/exit-e/err.cmdbadopt.ksh b/usr/src/cmd/mdb/test/exit-e/err.cmdbadopt.ksh new file mode 100644 index 0000000000..de50faeb01 --- /dev/null +++ b/usr/src/cmd/mdb/test/exit-e/err.cmdbadopt.ksh @@ -0,0 +1,2 @@ +$MDB -e '::typegraph' +exit $? diff --git a/usr/src/cmd/mdb/test/exit-e/err.enocmd.ksh b/usr/src/cmd/mdb/test/exit-e/err.enocmd.ksh new file mode 100644 index 0000000000..038f121b26 --- /dev/null +++ b/usr/src/cmd/mdb/test/exit-e/err.enocmd.ksh @@ -0,0 +1,2 @@ +$MDB -e '::commandthatdoesnotexist' +exit $? diff --git a/usr/src/cmd/mdb/test/exit-e/tst.output.ksh b/usr/src/cmd/mdb/test/exit-e/tst.output.ksh new file mode 100644 index 0000000000..13b5db072d --- /dev/null +++ b/usr/src/cmd/mdb/test/exit-e/tst.output.ksh @@ -0,0 +1 @@ +$MDB -e '0t2 << 0t10=K' diff --git a/usr/src/cmd/mdb/test/exit-e/tst.output.ksh.out b/usr/src/cmd/mdb/test/exit-e/tst.output.ksh.out new file mode 100644 index 0000000000..7a38ab6e65 --- /dev/null +++ b/usr/src/cmd/mdb/test/exit-e/tst.output.ksh.out @@ -0,0 +1 @@ + 800 diff --git a/usr/src/cmd/mdb/test/exit-e/tst.simple.ksh b/usr/src/cmd/mdb/test/exit-e/tst.simple.ksh new file mode 100644 index 0000000000..4c8a3c58ad --- /dev/null +++ b/usr/src/cmd/mdb/test/exit-e/tst.simple.ksh @@ -0,0 +1 @@ +$MDB -e '::dcmds' diff --git a/usr/src/cmd/mdb/test/mtest.sh b/usr/src/cmd/mdb/test/mtest.sh new file mode 100644 index 0000000000..f21d0faa21 --- /dev/null +++ b/usr/src/cmd/mdb/test/mtest.sh @@ -0,0 +1,235 @@ +#!/bin/bash +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 (c), Joyent, Inc. +# + +# +# mdb test driver +# +unalias -a +shopt -s xpg_echo +#set -o xtrace + +mt_arg0=$(basename $0) +mt_ksh="/usr/bin/ksh" +mt_mdb="/usr/bin/mdb" +mt_outdir= +mt_keep= +mt_all= +mt_tests= +mt_tnum=0 +mt_tfail=0 +mt_tsuc=0 + +function usage +{ + local msg="$*" + [[ -z "$msg" ]] || echo "$msg" 2>&1 + cat <<USAGE >&2 +Usage: $mt_arg0 [ -o dir ] [ -k ] [ -m executable ] [ -a | test ... ] + + -o dir Sets 'dir' as the output directory + -a Runs all tests, ignores tests passed in + -k Keep output from all tests, not just failures + -m mdb binary to test +USAGE + exit 2 +} + +function fatal +{ + local msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "$mt_arg0: $msg" >&2 + exit 1 +} + +function setup_outdir +{ + mt_outdir="$mt_outdir/$mt_arg0.$$" + mkdir -p $mt_outdir || fatal "failed to make output dir $mt_outdir" +} + +function run_single +{ + local name=$1 + local expect base ext exe command odir res reason input + + [[ -z "$name" ]] && fail "missing test to run" + base=${name##*/} + ext=${base##*.} + expect=${base%%.*} + odir="$mt_outdir/current" + [[ -z "$ext" ]] && fatal "found test without ext: $name" + [[ -z "$expect" ]] && fatal "found test without prefix: $name" + + case "$ext" in + "ksh") + command="$mt_ksh $name" + ;; + "mdb") + command="$mt_mdb" + input="$name" + ;; + "out") + # + # This is the file format for checking output against. + # + return 0 + ;; + *) + echo "skipping test $name (unknown extensino)" + return 0 + ;; + esac + + echo "Executing test $name ... \c" + mkdir -p "$odir" >/dev/null || fatal "can't make output directory" + if [[ -z "$input" ]]; then + MDB=$mt_mdb $command > "$odir/stdout" 2>"$odir/stderr" + res=$? + else + MDB=$mt_mdb $command < $input > "$odir/stdout" 2>"$odir/stderr" + res=$? + fi + + if [[ -f "$name.out" ]] && ! diff "$name.out" "$odir/stdout" >/dev/null; then + cp $name.out $odir/$base.out + reason="stdout mismatch" + elif [[ "$expect" == "tst" && $res -ne 0 ]]; then + reason="test exited $res, not zero" + elif [[ "$expect" == "err" && $res -eq 0 ]]; then + reason="test exited $res, not non-zero" + fi + + if [[ -n "$reason" ]]; then + echo "$reason" + ((mt_tfail++)) + mv "$odir" "$mt_outdir/failure.$mt_tfail" || fatal \ + "failed to move test output directory" + cp "$name" "$mt_outdir/failure.$mt_tfail/test" || fatal \ + "failed to copy test into output directory" + else + echo "passed" + ((mt_tsuc++)) + mv "$odir" "$mt_outdir/success.$mt_tsuc" || fatal \ + "failed to move test directory" + fi + + ((mt_tnum++)) +} + +function run_all +{ + local tests t + + tests=$(find . -type f -name '[tst,err]*.*.[ksh,mdb]*') + for t in $tests; do + run_single $t + done +} + +function welcome +{ + cat <<WELCOME +Starting tests... +mtest target: $mt_mdb +output directory: $mt_outdir +WELCOME +} + +function cleanup +{ + [[ -n "$mt_keep" ]] && return + rm -rf "$mt_outdir"/success.* || fatal \ + "failed to remove successful test cases" + if [[ $mt_tfail -eq 0 ]]; then + rmdir "$mt_outdir" || fatal \ + "failed to remove test output directory" + fi +} + +function goodbye +{ + cat <<EOF + +------------- +Results +------------- + +Tests passed: $mt_tsuc +Tests failed: $mt_tfail +Tests ran: $mt_tnum + +EOF + if [[ $mt_tfail -eq 0 ]]; then + echo "Congrats, mdb isn't completely broken, the tests pass". + else + echo "Some tests failed, you have some work to do." + fi +} + +while getopts ":ahko:m:" c $@; do + case "$c" in + a) + mt_all="y" + ;; + k) + mt_keep="y" + ;; + m) + mt_mdb="$OPTARG" + ;; + o) + mt_outdir="$OPTARG" + ;; + h) + usage + ;; + :) + usage "option requires an argument -- $OPTARG" + ;; + *) + usage "invalid option -- $OPTARG" + ;; + esac +done + +shift $((OPTIND-1)) + +[[ -z "$mt_all" && $# == 0 ]] && usage "no tests to run" + +[[ -x "$mt_mdb" ]] || fatal "unable to execute mdb binary: $mt_mdb" + +[[ -z "$mt_outdir" ]] && mt_outdir=/var/tmp + +setup_outdir +welcome + +if [[ ! -z "$mt_all" ]]; then + run_all +else + for t in $@; do + [[ -f $t ]] || fatal "cannot find test $t" + run_single $t + done +fi + +goodbye +cleanup + +# +# Exit 1 if we have tests that return non-zero +# +[[ $mt_tfai -eq 0 ]] diff --git a/usr/src/cmd/mdb/test/typedef/err.badid-leadnum.ksh b/usr/src/cmd/mdb/test/typedef/err.badid-leadnum.ksh new file mode 100644 index 0000000000..f297cf99f1 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badid-leadnum.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef lp32; ::typedef uint8_t 42foo' diff --git a/usr/src/cmd/mdb/test/typedef/err.badid-leadschar.ksh b/usr/src/cmd/mdb/test/typedef/err.badid-leadschar.ksh new file mode 100644 index 0000000000..5c7582b89c --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badid-leadschar.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef lp32; ::typedef uint8_t %foo' diff --git a/usr/src/cmd/mdb/test/typedef/err.badmodel.ksh b/usr/src/cmd/mdb/test/typedef/err.badmodel.ksh new file mode 100644 index 0000000000..28d6cf05a5 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badmodel.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c LLP64' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-extrabraces.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-extrabraces.ksh new file mode 100644 index 0000000000..3543aab1df --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-extrabraces.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[7]; {} void {**white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-neglenarr.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-neglenarr.ksh new file mode 100644 index 0000000000..ec41576179 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-neglenarr.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[-3]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayclose.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayclose.ksh new file mode 100644 index 0000000000..b91094ae44 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayclose.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[7; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noarraylen.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarraylen.ksh new file mode 100644 index 0000000000..4fe23fcee2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarraylen.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayopen.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayopen.ksh new file mode 100644 index 0000000000..9fe7e77200 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noarrayopen.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone7]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-nobraces.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-nobraces.ksh new file mode 100644 index 0000000000..d50d8e3fb9 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-nobraces.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct uintptr_t stone[7]; void **white;" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noclosebrace.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noclosebrace.ksh new file mode 100644 index 0000000000..4b20fac8c5 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noclosebrace.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[7]; void **white; " gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-nomembers.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomembers.ksh new file mode 100644 index 0000000000..9fd82a01cc --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomembers.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemname.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemname.ksh new file mode 100644 index 0000000000..e1e4eacf13 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemname.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { void; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemsemi.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemsemi.ksh new file mode 100644 index 0000000000..9ab93a792f --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-nomemsemi.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[7]; void **white }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noopenbrace.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noopenbrace.ksh new file mode 100644 index 0000000000..450b35ade2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noopenbrace.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct uintptr_t stone[7]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-noquotes.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-noquotes.ksh new file mode 100644 index 0000000000..789caf63b0 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-noquotes.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef struct { uintptr_t stone[7]; void **white; } gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-repmemname.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-repmemname.ksh new file mode 100644 index 0000000000..c00aca88fb --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-repmemname.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[7]; void **stone; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-vlaonly.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-vlaonly.ksh new file mode 100644 index 0000000000..a678d136b6 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-vlaonly.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[]; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badstruct-zerolenarr.ksh b/usr/src/cmd/mdb/test/typedef/err.badstruct-zerolenarr.ksh new file mode 100644 index 0000000000..7999c97a5a --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badstruct-zerolenarr.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "struct { uintptr_t stone[0]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.badunion-hasvla.ksh b/usr/src/cmd/mdb/test/typedef/err.badunion-hasvla.ksh new file mode 100644 index 0000000000..57a82a7752 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.badunion-hasvla.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "union { int foo; uintptr_t stone[]; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.extraargs.ksh b/usr/src/cmd/mdb/test/typedef/err.extraargs.ksh new file mode 100644 index 0000000000..510797265b --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.extraargs.ksh @@ -0,0 +1 @@ +$MDB -e "::typedef -c lp32; ::typedef uint8_t rm_t extra_t" diff --git a/usr/src/cmd/mdb/test/typedef/err.noargs.ksh b/usr/src/cmd/mdb/test/typedef/err.noargs.ksh new file mode 100644 index 0000000000..77eeacc5f2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.noargs.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef' diff --git a/usr/src/cmd/mdb/test/typedef/err.nokeyword.ksh b/usr/src/cmd/mdb/test/typedef/err.nokeyword.ksh new file mode 100644 index 0000000000..9a5e1a1fcc --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.nokeyword.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c lp32; ::typedef "{ uintptr_t stone[7]; void **white; }" gift_t' diff --git a/usr/src/cmd/mdb/test/typedef/err.nomodel.ksh b/usr/src/cmd/mdb/test/typedef/err.nomodel.ksh new file mode 100644 index 0000000000..4614ac23d6 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.nomodel.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef -c' diff --git a/usr/src/cmd/mdb/test/typedef/err.noname.ksh b/usr/src/cmd/mdb/test/typedef/err.noname.ksh new file mode 100644 index 0000000000..04ebca1204 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.noname.ksh @@ -0,0 +1 @@ +$MDB -e '::typedef int' diff --git a/usr/src/cmd/mdb/test/typedef/err.typeexists.ksh b/usr/src/cmd/mdb/test/typedef/err.typeexists.ksh new file mode 100644 index 0000000000..a1158cd830 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/err.typeexists.ksh @@ -0,0 +1 @@ +$MDB /lib/libc.so -e '::typedef uint8_t uint16_t' diff --git a/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb b/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb new file mode 100644 index 0000000000..27de9428c6 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb @@ -0,0 +1,4 @@ +::typedef -c lp32 +::typedef "struct { uintptr_t stone[7]; void **white; }" gift_t +::sizeof gift_t +::print -at gift_t diff --git a/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb.out new file mode 100644 index 0000000000..605e0facfc --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.anonstruct.mdb.out @@ -0,0 +1,5 @@ +sizeof (gift_t) = 0x28 +0 gift_t { + 0 uintptr_t [7] stone + 20 void **white +} diff --git a/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb b/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb new file mode 100644 index 0000000000..1aa17b5366 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb @@ -0,0 +1,4 @@ +::typedef -c lp64 +::typedef "union { int frodo; char sam; long gandalf; }" ringbearer_t; +::sizeof ringbearer_t +::print -at ringbearer_t diff --git a/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb.out new file mode 100644 index 0000000000..0a762dc1f8 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.anonunion.mdb.out @@ -0,0 +1,6 @@ +sizeof (ringbearer_t) = 8 +0 ringbearer_t { + 0 int frodo + 0 char sam + 0 long gandalf +} diff --git a/usr/src/cmd/mdb/test/typedef/tst.cleanupstruct.ksh b/usr/src/cmd/mdb/test/typedef/tst.cleanupstruct.ksh new file mode 100644 index 0000000000..1abf7540ce --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.cleanupstruct.ksh @@ -0,0 +1,22 @@ +# +# One of the problems that we can encounter involves trying to typedef a struct +# that has an error in it. The problem here is that we actually create the type +# itself for the struct before we add members. So what we need is something that +# will fail validation. So here we go! +# + +TMPFILE="/tmp/$(mktemp mtest.XXXXXX)" +if [[ -z "$TMPFILE" ]]; then + echo "Failed to get a temp file" 2>&1 + exit 1 +fi + +$MDB <<EOF +::typedef "struct foo { int r; }" foo_t +::typedef -l ! cat > $TMPFILE +EOF + +DATA=$(cat $TMPFILE) +rm -f $TMPFILE + +[[ -z $DATA ]] diff --git a/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb b/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb new file mode 100644 index 0000000000..12c28075a8 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb @@ -0,0 +1,27 @@ +::typedef -c LP32 +::sizeof int8_t +::sizeof int16_t +::sizeof int32_t +::sizeof int64_t +::sizeof uint8_t +::sizeof uint16_t +::sizeof uint32_t +::sizeof uint64_t +::sizeof intptr_t +::sizeof uintptr_t +::sizeof uchar_t +::sizeof ushort_t +::sizeof uint_t +::sizeof ulong_t +::sizeof u_longlong_t +::sizeof ptrdiff_t +::sizeof signed +::sizeof unsigned +::sizeof void +::sizeof char +::sizeof short +::sizeof int +::sizeof long +::sizeof _Bool +::sizeof float +::sizeof double diff --git a/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb.out new file mode 100644 index 0000000000..792f42fbf2 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.deftypes32.mdb.out @@ -0,0 +1,26 @@ +sizeof (int8_t) = 1 +sizeof (int16_t) = 2 +sizeof (int32_t) = 4 +sizeof (int64_t) = 8 +sizeof (uint8_t) = 1 +sizeof (uint16_t) = 2 +sizeof (uint32_t) = 4 +sizeof (uint64_t) = 8 +sizeof (intptr_t) = 4 +sizeof (uintptr_t) = 4 +sizeof (uchar_t) = 1 +sizeof (ushort_t) = 2 +sizeof (uint_t) = 4 +sizeof (ulong_t) = 4 +sizeof (u_longlong_t) = 8 +sizeof (ptrdiff_t) = 4 +sizeof (signed) = 4 +sizeof (unsigned) = 4 +sizeof (void) = 0 +sizeof (char) = 1 +sizeof (short) = 2 +sizeof (int) = 4 +sizeof (long) = 4 +sizeof (_Bool) = 1 +sizeof (float) = 4 +sizeof (double) = 8 diff --git a/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb b/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb new file mode 100644 index 0000000000..5ae94cdea0 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb @@ -0,0 +1,27 @@ +::typedef -c LP64 +::sizeof int8_t +::sizeof int16_t +::sizeof int32_t +::sizeof int64_t +::sizeof uint8_t +::sizeof uint16_t +::sizeof uint32_t +::sizeof uint64_t +::sizeof intptr_t +::sizeof uintptr_t +::sizeof uchar_t +::sizeof ushort_t +::sizeof uint_t +::sizeof ulong_t +::sizeof u_longlong_t +::sizeof ptrdiff_t +::sizeof signed +::sizeof unsigned +::sizeof void +::sizeof char +::sizeof short +::sizeof int +::sizeof long +::sizeof _Bool +::sizeof float +::sizeof double diff --git a/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb.out new file mode 100644 index 0000000000..83b85b943a --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.deftypes64.mdb.out @@ -0,0 +1,26 @@ +sizeof (int8_t) = 1 +sizeof (int16_t) = 2 +sizeof (int32_t) = 4 +sizeof (int64_t) = 8 +sizeof (uint8_t) = 1 +sizeof (uint16_t) = 2 +sizeof (uint32_t) = 4 +sizeof (uint64_t) = 8 +sizeof (intptr_t) = 8 +sizeof (uintptr_t) = 8 +sizeof (uchar_t) = 1 +sizeof (ushort_t) = 2 +sizeof (uint_t) = 4 +sizeof (ulong_t) = 8 +sizeof (u_longlong_t) = 8 +sizeof (ptrdiff_t) = 8 +sizeof (signed) = 4 +sizeof (unsigned) = 4 +sizeof (void) = 0 +sizeof (char) = 1 +sizeof (short) = 2 +sizeof (int) = 4 +sizeof (long) = 8 +sizeof (_Bool) = 1 +sizeof (float) = 4 +sizeof (double) = 8 diff --git a/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb b/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb new file mode 100644 index 0000000000..e9009d7b68 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.dellist.mdb @@ -0,0 +1,3 @@ +::typdef -c lp32 +::typedef -d +::typedef -l diff --git a/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb b/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb new file mode 100644 index 0000000000..6c7505ac1c --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.emptylist.mdb @@ -0,0 +1 @@ +::typedef -l diff --git a/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh b/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh new file mode 100644 index 0000000000..cf517cf937 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh @@ -0,0 +1,6 @@ +$MDB /lib/libc.so <<EOF +::typedef uint8_t rm_t +::typedef -l +::print -at rm_t +::sizeof rm_t +EOF diff --git a/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh.out b/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh.out new file mode 100644 index 0000000000..d37ffafbfb --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.libctype.ksh.out @@ -0,0 +1,4 @@ +uint8_t +rm_t +0 rm_t +sizeof (rm_t) = 1 diff --git a/usr/src/cmd/mdb/test/typedef/tst.models.ksh b/usr/src/cmd/mdb/test/typedef/tst.models.ksh new file mode 100644 index 0000000000..8537ec443c --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.models.ksh @@ -0,0 +1,11 @@ +lp64m="lp64 Lp64 LP64 lP64" +lp32m="lp32 Lp32 LP32 lP32" +ilp32m="ilp32 ilP32 iLp32 iLP32 Ilp32 IlP32 ILp32 ILP32" +for m in $lp64m $lp32m $ilp32m; do + $MDB -e "::typedef -c $m" + if [[ ! $? -eq 0 ]]; then + echo "failed to create model $m" 2>&1 + exit 1 + fi +done +exit 0 diff --git a/usr/src/cmd/mdb/test/typedef/tst.struct.mdb b/usr/src/cmd/mdb/test/typedef/tst.struct.mdb new file mode 100644 index 0000000000..2e0206e7ec --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.struct.mdb @@ -0,0 +1,6 @@ +::typedef -c lp32 +::typedef "struct gift { uintptr_t stone[7]; void **white; }" gift_t +::sizeof gift_t +::print -at gift_t +::sizeof struct gift +::print -at struct gift diff --git a/usr/src/cmd/mdb/test/typedef/tst.struct.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.struct.mdb.out new file mode 100644 index 0000000000..9a7d801742 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.struct.mdb.out @@ -0,0 +1,10 @@ +sizeof (gift_t) = 0x28 +0 gift_t { + 0 uintptr_t [7] stone + 20 void **white +} +sizeof (struct gift) = 0x28 +0 struct gift { + 0 uintptr_t [7] stone + 20 void **white +} diff --git a/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb b/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb new file mode 100644 index 0000000000..85b3068e00 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb @@ -0,0 +1,4 @@ +::typedef -c lp32 +::typedef "struct list { struct list *prev; struct list *next; }" list_t +::sizeof list_t +::print -at list_t diff --git a/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb.out new file mode 100644 index 0000000000..a6f4823ad1 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.structselfref.mdb.out @@ -0,0 +1,5 @@ +sizeof (list_t) = 0x10 +0 list_t { + 0 struct list *prev + 8 struct list *next +} diff --git a/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb b/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb new file mode 100644 index 0000000000..27cd56c186 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb @@ -0,0 +1,4 @@ +::typedef -c lp32 +::typedef "struct gift { uintptr_t stone[7]; void **white; char owner[]; }" gift_t +::sizeof gift_t +::print -at gift_t diff --git a/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb.out new file mode 100644 index 0000000000..0a0d3d4029 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.structvla.mdb.out @@ -0,0 +1,6 @@ +sizeof (gift_t) = 0x28 +0 gift_t { + 0 uintptr_t [7] stone + 20 void **white + 28 char [0] owner +} diff --git a/usr/src/cmd/mdb/test/typedef/tst.union.mdb b/usr/src/cmd/mdb/test/typedef/tst.union.mdb new file mode 100644 index 0000000000..966446caee --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.union.mdb @@ -0,0 +1,6 @@ +::typedef -c lp64 +::typedef "union ringbearer { int frodo; char sam; long gandalf; }" ringbearer_t; +::sizeof ringbearer_t +::print -at ringbearer_t +::sizeof union ringbearer +::print -at union ringbearer diff --git a/usr/src/cmd/mdb/test/typedef/tst.union.mdb.out b/usr/src/cmd/mdb/test/typedef/tst.union.mdb.out new file mode 100644 index 0000000000..2afc2eabb9 --- /dev/null +++ b/usr/src/cmd/mdb/test/typedef/tst.union.mdb.out @@ -0,0 +1,12 @@ +sizeof (ringbearer_t) = 8 +0 ringbearer_t { + 0 int frodo + 0 char sam + 0 long gandalf +} +sizeof (union ringbearer) = 8 +0 union ringbearer { + 0 int frodo + 0 char sam + 0 long gandalf +} |
