diff options
Diffstat (limited to 'usr/src/cmd/mdb/common')
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_cmds.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_help.c | 18 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_help.h | 5 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_print.c | 113 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_print.h | 4 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_tab.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/v8/mdb_v8.c | 128 |
7 files changed, 203 insertions, 74 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c index 4dc179c941..c9cf91b14f 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c @@ -2943,7 +2943,8 @@ const mdb_dcmd_t mdb_dcmd_builtins[] = { { "grep", "?expr", "print dot if expression is true", cmd_grep }, { "head", "-num|-n num", "limit number of elements in pipe", cmd_head, head_help }, - { "help", "[cmd]", "list commands/command help", cmd_help }, + { "help", "[cmd]", "list commands/command help", cmd_help, NULL, + cmd_help_tab }, { "list", "?type member [variable]", "walk list using member as link pointer", cmd_list, NULL, mdb_tab_complete_mt }, @@ -2962,7 +2963,8 @@ const mdb_dcmd_t mdb_dcmd_builtins[] = { "print the contents of a data structure", cmd_print, print_help, cmd_print_tab }, { "printf", "?[format] [type] [member ... ]", "print and format the " - "member(s) of a data structure", cmd_printf, printf_help }, + "member(s) of a data structure", cmd_printf, printf_help, + cmd_printf_tab }, { "regs", NULL, "print general purpose registers", cmd_notsup }, { "set", "[-wF] [+/-o opt] [-s dist] [-I path] [-L path] [-P prompt]", "get/set debugger properties", cmd_set }, diff --git a/usr/src/cmd/mdb/common/mdb/mdb_help.c b/usr/src/cmd/mdb/common/mdb/mdb_help.c index 2fe3ad56a1..95d3ec6af3 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_help.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_help.c @@ -22,6 +22,7 @@ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <mdb/mdb_modapi.h> @@ -252,6 +253,23 @@ cmd_help(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +int +cmd_help_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + if (argc == 0 && !(flags & DCMD_TAB_SPACE)) + return (0); + + if (argc > 1) + return (0); + + if (argc == 0) + return (mdb_tab_complete_dcmd(mcp, NULL)); + else + return (mdb_tab_complete_dcmd(mcp, argv[0].a_un.a_str)); +} + + static int print_dcmd_def(mdb_var_t *v, void *private) { diff --git a/usr/src/cmd/mdb/common/mdb/mdb_help.h b/usr/src/cmd/mdb/common/mdb/mdb_help.h index 3c086e4065..92516a43dd 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_help.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_help.h @@ -22,12 +22,13 @@ /* * Copyright (c) 1998-1999 by Sun Microsystems, Inc. * All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _MDB_HELP_H #define _MDB_HELP_H -#pragma ident "%Z%%M% %I% %E% SMI" +#include <mdb/mdb_tab.h> #ifdef __cplusplus extern "C" { @@ -35,11 +36,13 @@ extern "C" { #ifdef _MDB + extern int cmd_dmods(uintptr_t, uint_t, int, const mdb_arg_t *); extern int cmd_dcmds(uintptr_t, uint_t, int, const mdb_arg_t *); extern int cmd_walkers(uintptr_t, uint_t, int, const mdb_arg_t *); extern int cmd_formats(uintptr_t, uint_t, int, const mdb_arg_t *); extern int cmd_help(uintptr_t, uint_t, int, const mdb_arg_t *); +extern int cmd_help_tab(mdb_tab_cookie_t *, uint_t, int, const mdb_arg_t *); extern int cmd_which(uintptr_t, uint_t, int, const mdb_arg_t *); #endif /* _MDB */ diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.c b/usr/src/cmd/mdb/common/mdb/mdb_print.c index ee40bf950e..97971876de 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_print.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c @@ -2006,45 +2006,19 @@ parse_member(printarg_t *pap, const char *str, mdb_ctf_id_t id, return (0); } -int -cmd_print_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc, +static int +cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc, const mdb_arg_t *argv) { char tn[MDB_SYM_NAMLEN]; char member[64]; - int i, dummy, delim, kind; + int delim, kind; int ret = 0; mdb_ctf_id_t id, rid; mdb_ctf_arinfo_t ar; char *start, *end; ulong_t dul; - /* - * This getopts is only here to make the tab completion work better when - * including options in the ::print arguments. None of the values should - * be used. This should only be updated with additional arguments, if - * they are added to cmd_print. - */ - i = mdb_getopts(argc, argv, - 'a', MDB_OPT_SETBITS, PA_SHOWADDR, &dummy, - 'C', MDB_OPT_SETBITS, TRUE, &dummy, - 'c', MDB_OPT_UINTPTR, &dummy, - 'd', MDB_OPT_SETBITS, PA_INTDEC, &dummy, - 'h', MDB_OPT_SETBITS, PA_SHOWHOLES, &dummy, - 'i', MDB_OPT_SETBITS, TRUE, &dummy, - 'L', MDB_OPT_SETBITS, TRUE, &dummy, - 'l', MDB_OPT_UINTPTR, &dummy, - 'n', MDB_OPT_SETBITS, PA_NOSYMBOLIC, &dummy, - 'p', MDB_OPT_SETBITS, TRUE, &dummy, - 's', MDB_OPT_UINTPTR, &dummy, - 'T', MDB_OPT_SETBITS, PA_SHOWTYPE | PA_SHOWBASETYPE, &dummy, - 't', MDB_OPT_SETBITS, PA_SHOWTYPE, &dummy, - 'x', MDB_OPT_SETBITS, PA_INTHEX, &dummy, - NULL); - - argc -= i; - argv += i; - if (argc == 0 && !(flags & DCMD_TAB_SPACE)) return (0); @@ -2168,6 +2142,42 @@ cmd_print_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc, * already have in rid. */ return (mdb_tab_complete_member_by_id(mcp, rid, member)); + +} + +int +cmd_print_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + int i, dummy; + + /* + * This getopts is only here to make the tab completion work better when + * including options in the ::print arguments. None of the values should + * be used. This should only be updated with additional arguments, if + * they are added to cmd_print. + */ + i = mdb_getopts(argc, argv, + 'a', MDB_OPT_SETBITS, PA_SHOWADDR, &dummy, + 'C', MDB_OPT_SETBITS, TRUE, &dummy, + 'c', MDB_OPT_UINTPTR, &dummy, + 'd', MDB_OPT_SETBITS, PA_INTDEC, &dummy, + 'h', MDB_OPT_SETBITS, PA_SHOWHOLES, &dummy, + 'i', MDB_OPT_SETBITS, TRUE, &dummy, + 'L', MDB_OPT_SETBITS, TRUE, &dummy, + 'l', MDB_OPT_UINTPTR, &dummy, + 'n', MDB_OPT_SETBITS, PA_NOSYMBOLIC, &dummy, + 'p', MDB_OPT_SETBITS, TRUE, &dummy, + 's', MDB_OPT_UINTPTR, &dummy, + 'T', MDB_OPT_SETBITS, PA_SHOWTYPE | PA_SHOWBASETYPE, &dummy, + 't', MDB_OPT_SETBITS, PA_SHOWTYPE, &dummy, + 'x', MDB_OPT_SETBITS, PA_INTHEX, &dummy, + NULL); + + argc -= i; + argv += i; + + return (cmd_print_tab_common(mcp, flags, argc, argv)); } /* @@ -2758,6 +2768,51 @@ enum { }; int +cmd_printf_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + int ii; + char *f; + + /* + * If argc doesn't have more than what should be the format string, + * ignore it. + */ + if (argc <= 1) + return (0); + + /* + * Because we aren't leveraging the lex and yacc engine, we have to + * manually walk the arguments to find both the first and last + * open/close quote of the format string. + */ + f = strchr(argv[0].a_un.a_str, '"'); + if (f == NULL) + return (0); + + f = strchr(f + 1, '"'); + if (f != NULL) { + ii = 0; + } else { + for (ii = 1; ii < argc; ii++) { + f = strchr(argv[ii].a_un.a_str, '"'); + if (f != NULL) + break; + } + /* Never found */ + if (ii == argc) + return (0); + } + + ii++; + argc -= ii; + argv += ii; + + + return (cmd_print_tab_common(mcp, flags, argc, argv)); +} + +int cmd_printf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { char type[MDB_SYM_NAMLEN]; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.h b/usr/src/cmd/mdb/common/mdb/mdb_print.h index 40ef877466..9f4d0ba0dd 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_print.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_print.h @@ -25,9 +25,6 @@ * Copyright (c) 2012 Joyent, Inc. All rights reserved. */ -/* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. - */ #ifndef _MDB_PRINT_H #define _MDB_PRINT_H @@ -50,6 +47,7 @@ extern int cmd_print(uintptr_t, uint_t, int, const mdb_arg_t *); extern int cmd_print_tab(mdb_tab_cookie_t *, uint_t, int, const mdb_arg_t *); extern void print_help(void); extern int cmd_printf(uintptr_t, uint_t, int, const mdb_arg_t *); +extern int cmd_printf_tab(mdb_tab_cookie_t *, uint_t, int, const mdb_arg_t *); extern void printf_help(void); #endif /* _MDB */ diff --git a/usr/src/cmd/mdb/common/mdb/mdb_tab.c b/usr/src/cmd/mdb/common/mdb/mdb_tab.c index bf2dbb6f55..ebf9a637f2 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_tab.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_tab.c @@ -338,7 +338,8 @@ tab_complete_dcmd(mdb_var_t *v, void *arg) int mdb_tab_complete_dcmd(mdb_tab_cookie_t *mcp, const char *dcmd) { - mdb_tab_setmbase(mcp, dcmd); + if (dcmd != NULL) + mdb_tab_setmbase(mcp, dcmd); mdb_nv_sort_iter(&mdb.m_dcmds, tab_complete_dcmd, mcp, UM_GC | UM_SLEEP); return (0); diff --git a/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c b/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c index 244ef8bdd2..73542d5a7f 100644 --- a/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c +++ b/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c @@ -126,6 +126,9 @@ static intptr_t V8_PROP_TYPE_FIELD; static intptr_t V8_PROP_FIRST_PHANTOM; static intptr_t V8_PROP_TYPE_MASK; +static intptr_t V8_TYPE_JSOBJECT = -1; +static intptr_t V8_TYPE_FIXEDARRAY = -1; + /* * Although we have this information in v8_classes, the following offsets are * defined explicitly because they're used directly in code below. @@ -261,6 +264,7 @@ static int conf_update_type(v8_cfg_t *, const char *); static int conf_update_frametype(v8_cfg_t *, const char *); static void conf_class_compute_offsets(v8_class_t *); +static int read_typebyte(uint8_t *, uintptr_t); static int heap_offset(const char *, const char *, ssize_t *); /* @@ -271,6 +275,7 @@ static int autoconfigure(v8_cfg_t *cfgp) { v8_class_t *clp; + v8_enum_t *ep; struct v8_constant *cnp; int ii; @@ -310,6 +315,23 @@ autoconfigure(v8_cfg_t *cfgp) } /* + * Load type values for well-known classes that we use a lot. + */ + for (ep = v8_types; ep->v8e_name[0] != '\0'; ep++) { + if (strcmp(ep->v8e_name, "JSObject") == 0) + V8_TYPE_JSOBJECT = ep->v8e_value; + + if (strcmp(ep->v8e_name, "FixedArray") == 0) + V8_TYPE_FIXEDARRAY = ep->v8e_value; + } + + if (V8_TYPE_JSOBJECT == -1 || V8_TYPE_FIXEDARRAY == -1) { + mdb_warn("couldn't find %s type\n", + V8_TYPE_JSOBJECT == -1 ? "JSObject" : "FixedArray"); + return (-1); + } + + /* * Finally, load various class offsets. */ for (ii = 0; ii < v8_noffsets; ii++) { @@ -780,8 +802,18 @@ read_heap_double(double *valp, uintptr_t addr, ssize_t off) static int read_heap_array(uintptr_t addr, uintptr_t **retp, size_t *lenp, int flags) { + uint8_t type; uintptr_t len; + if (!V8_IS_HEAPOBJECT(addr)) + return (-1); + + if (read_typebyte(&type, addr) != 0) + return (-1); + + if (type != V8_TYPE_FIXEDARRAY) + return (-1); + if (read_heap_smi(&len, addr, V8_OFF_FIXEDARRAY_LENGTH) != 0) return (-1); @@ -1212,7 +1244,7 @@ jsobj_properties(uintptr_t addr, if (read_typebyte(&type, ptr) != 0) return (-1); - if (strcmp(enum_lookup_str(v8_types, type, ""), "FixedArray") != 0) + if (type != V8_TYPE_FIXEDARRAY) return (func(NULL, 0, arg)); if (read_heap_array(ptr, &props, &nprops, UM_SLEEP) != 0) @@ -1337,7 +1369,13 @@ jsfunc_lineno(uintptr_t lendsp, uintptr_t tokpos, char *buf, size_t buflen) uintptr_t *data; if (jsobj_is_undefined(lendsp)) { - mdb_snprintf(buf, buflen, "position %d", tokpos); + /* + * The token position is an SMI, but it comes in as its raw + * value so we can more easily compare it to values in the line + * endings table. If we're just printing the position directly, + * we must convert it here. + */ + mdb_snprintf(buf, buflen, "position %d", V8_SMI_VALUE(tokpos)); return (0); } @@ -1893,6 +1931,17 @@ do_jsframe_special(uintptr_t fptr, uintptr_t raddr) const char *ftypename; /* + * First see if this looks like a native frame rather than a JavaScript + * frame. We check this by asking MDB to print the return address + * symbolically. If that works, we assume this was NOT a V8 frame, + * since those are never in the symbol table. + */ + if (mdb_snprintf(NULL, 0, "%A", raddr) > 1) { + mdb_printf("%p %a\n", fptr, raddr); + return (0); + } + + /* * Figure out what kind of frame this is using the same algorithm as * V8's ComputeType function. First, look for an ArgumentsAdaptorFrame. */ @@ -2185,22 +2234,8 @@ findjsobjects_range(findjsobjects_state_t *fjs, uintptr_t addr, uintptr_t size) uintptr_t limit; findjsobjects_stats_t *stats = &fjs->fjs_stats; uint8_t type; - int jsobject = -1, fixedarray = -1; - v8_enum_t *ep; + int jsobject = V8_TYPE_JSOBJECT; - for (ep = v8_types; ep->v8e_name[0] != '\0'; ep++) { - if (strcmp(ep->v8e_name, "JSObject") == 0) - jsobject = ep->v8e_value; - - if (strcmp(ep->v8e_name, "FixedArray") == 0) - fixedarray = ep->v8e_value; - } - - if (jsobject == -1 || fixedarray == -1) { - v8_warn("couldn't find %s type\n", - jsobject == -1 ? "JSObject" : "FixedArray"); - return (-1); - } for (limit = addr + size; addr < limit; addr++) { findjsobjects_instance_t *inst; @@ -2732,7 +2767,7 @@ dcmd_v8array(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (read_typebyte(&type, addr) != 0) return (DCMD_ERR); - if (strcmp(enum_lookup_str(v8_types, type, ""), "FixedArray") != 0) { + if (type != V8_TYPE_FIXEDARRAY) { mdb_warn("%p is not an instance of FixedArray\n", addr); return (DCMD_ERR); } @@ -2870,7 +2905,7 @@ walk_jsframes_init(mdb_walk_state_t *wsp) static int walk_jsframes_step(mdb_walk_state_t *wsp) { - uintptr_t ftype, addr, next; + uintptr_t addr, next; int rv; addr = wsp->walk_addr; @@ -2879,15 +2914,6 @@ walk_jsframes_step(mdb_walk_state_t *wsp) if (rv != WALK_NEXT) return (rv); - /* - * Figure out the type of this frame. - */ - if (mdb_vread(&ftype, sizeof (ftype), addr + V8_OFF_FP_MARKER) == -1) - return (WALK_ERR); - - if (V8_IS_SMI(ftype) && V8_SMI_VALUE(ftype) == 0) - return (WALK_DONE); - if (mdb_vread(&next, sizeof (next), addr) == -1) return (WALK_ERR); @@ -2952,8 +2978,8 @@ static const mdb_walker_t v8_mdb_walkers[] = { static mdb_modinfo_t v8_mdb = { MDB_API_VERSION, v8_mdb_dcmds, v8_mdb_walkers }; -const mdb_modinfo_t * -_mdb_init(void) +static void +configure(void) { uintptr_t v8major, v8minor, v8build, v8patch; GElf_Sym sym; @@ -2967,7 +2993,7 @@ _mdb_init(void) mdb_readsym(&v8patch, sizeof (v8patch), "_ZN2v88internal7Version6patch_E") == -1) { mdb_warn("failed to determine V8 version"); - return (&v8_mdb); + return; } mdb_printf("V8 version: %d.%d.%d.%d\n", v8major, v8minor, v8build, @@ -2982,24 +3008,50 @@ _mdb_init(void) mdb_warn("failed to autoconfigure from target\n"); else - mdb_printf("Autoconfigured V8 support from target.\n"); + mdb_printf("Autoconfigured V8 support from target\n"); - return (&v8_mdb); + return; } if (v8major == 3 && v8minor == 1 && v8build == 8 && autoconfigure(&v8_cfg_04) == 0) { - mdb_printf("Configured V8 support based on node v0.4"); - return (&v8_mdb); + mdb_printf("Configured V8 support based on node v0.4\n"); + return; } if (v8major == 3 && v8minor == 6 && v8build == 6 && autoconfigure(&v8_cfg_06) == 0) { - mdb_printf("Configured V8 support based on node v0.6"); - return (&v8_mdb); + mdb_printf("Configured V8 support based on node v0.6\n"); + return; } mdb_printf("mdb_v8: target has no debug metadata and no existing " - "config found"); + "config found\n"); +} + +static void +enable_demangling(void) +{ + const char *symname = "_ZN2v88internal7Version6major_E"; + GElf_Sym sym; + char buf[64]; + + /* + * Try to determine whether C++ symbol demangling has been enabled. If + * not, enable it. + */ + if (mdb_lookup_by_name("_ZN2v88internal7Version6major_E", &sym) != 0) + return; + + (void) mdb_snprintf(buf, sizeof (buf), "%a", sym.st_value); + if (strstr(buf, symname) != NULL) + (void) mdb_eval("$G"); +} + +const mdb_modinfo_t * +_mdb_init(void) +{ + configure(); + enable_demangling(); return (&v8_mdb); } |