summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
commit04b244dd661c24b510ac22936decfc0972d202d3 (patch)
tree3ebfef98afc303fddf3415d6fba64e8682f495e8 /usr/src/cmd/mdb
parenteac250589e41f1b705e1b7427b02b3379aac9f9e (diff)
parenta69187741b83640a90dd8586195456dd50c016a8 (diff)
downloadillumos-joyent-20120517.tar.gz
Merge git.joyent.com:illumos-joyent20120517
Diffstat (limited to 'usr/src/cmd/mdb')
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_cmds.c6
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_help.c18
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_help.h5
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.c113
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.h4
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_tab.c3
-rw-r--r--usr/src/cmd/mdb/common/modules/v8/mdb_v8.c128
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);
}