summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2013-02-14 06:25:28 +0000
committerBryan Cantrill <bryan@joyent.com>2013-02-14 06:25:28 +0000
commite21124bb98fafb8524e3c1e78aace57b02b164f0 (patch)
tree4ccbeee967c592e8afa3f4c8df293b6d969bf709
parent0c15e0b9f89902ab4d9d0917f3c7832acb420422 (diff)
downloadillumos-joyent-e21124bb98fafb8524e3c1e78aace57b02b164f0.tar.gz
OS-1898 would like an mdb_v8 walker to iterate over property values
OS-1899 ::jsprint should allow more than one optional member
-rw-r--r--usr/src/cmd/mdb/common/modules/v8/mdb_v8.c149
1 files changed, 120 insertions, 29 deletions
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 f5bd662a0a..3d5b400f8f 100644
--- a/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c
+++ b/usr/src/cmd/mdb/common/modules/v8/mdb_v8.c
@@ -3227,48 +3227,56 @@ dcmd_jsprint(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (opt_b)
jsop.jsop_baseaddr = addr;
- if (i < argc - 1)
- return (DCMD_USAGE);
+ do {
+ if (i != argc) {
+ const mdb_arg_t *member = &argv[i++];
- if (i != argc) {
- const mdb_arg_t *member = &argv[argc - 1];
+ if (member->a_type != MDB_TYPE_STRING)
+ return (DCMD_USAGE);
- if (member->a_type != MDB_TYPE_STRING)
- return (DCMD_USAGE);
-
- jsop.jsop_member = member->a_un.a_str;
- }
+ jsop.jsop_member = member->a_un.a_str;
+ }
- for (;;) {
- if ((buf = bufp = mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL)
- return (DCMD_ERR);
+ for (;;) {
+ if ((buf = bufp =
+ mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL)
+ return (DCMD_ERR);
- jsop.jsop_bufp = &bufp;
- jsop.jsop_lenp = &len;
+ jsop.jsop_bufp = &bufp;
+ jsop.jsop_lenp = &len;
- rv = jsobj_print(addr, &jsop);
+ rv = jsobj_print(addr, &jsop);
- if (len > 0)
- break;
+ if (len > 0)
+ break;
- mdb_free(buf, bufsz);
- bufsz <<= 1;
- len = bufsz;
- }
+ mdb_free(buf, bufsz);
+ bufsz <<= 1;
+ len = bufsz;
+ }
- if (jsop.jsop_member && !jsop.jsop_found) {
- if (rv != 0)
+ if (jsop.jsop_member == NULL && rv != 0)
return (DCMD_ERR);
- mdb_warn("'%s' not found in %p\n", jsop.jsop_member, addr);
+ if (jsop.jsop_member && !jsop.jsop_found) {
+ if (jsop.jsop_baseaddr)
+ (void) mdb_printf("%p: ", jsop.jsop_baseaddr);
+
+ (void) mdb_printf("undefined%s",
+ i < argc ? " " : "");
+ } else {
+ (void) mdb_printf("%s%s", buf, i < argc &&
+ !isspace(buf[strlen(buf) - 1]) ? " " : "");
+ }
+
mdb_free(buf, bufsz);
- return (DCMD_ERR);
- }
+ jsop.jsop_found = B_FALSE;
+ jsop.jsop_baseaddr = NULL;
+ } while (i < argc);
- (void) mdb_printf("%s\n", buf);
- mdb_free(buf, bufsz);
+ mdb_printf("\n");
- return (rv == 0 ? DCMD_OK : DCMD_ERR);
+ return (DCMD_OK);
}
/* ARGSUSED */
@@ -3507,6 +3515,87 @@ walk_jsframes_step(mdb_walk_state_t *wsp)
return (WALK_NEXT);
}
+typedef struct jsprop_walk_data {
+ int jspw_nprops;
+ int jspw_current;
+ uintptr_t *jspw_props;
+} jsprop_walk_data_t;
+
+/*ARGSUSED*/
+static int
+walk_jsprop_nprops(const char *desc, uintptr_t val, void *arg)
+{
+ jsprop_walk_data_t *jspw = arg;
+ jspw->jspw_nprops++;
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+walk_jsprop_props(const char *desc, uintptr_t val, void *arg)
+{
+ jsprop_walk_data_t *jspw = arg;
+ jspw->jspw_props[jspw->jspw_current++] = val;
+
+ return (0);
+}
+
+static int
+walk_jsprop_init(mdb_walk_state_t *wsp)
+{
+ jsprop_walk_data_t *jspw;
+ uintptr_t addr;
+ uint8_t type;
+
+ if ((addr = wsp->walk_addr) == NULL) {
+ mdb_warn("'jsprop' does not support global walks\n");
+ return (WALK_ERR);
+ }
+
+ if (!V8_IS_HEAPOBJECT(addr) || read_typebyte(&type, addr) != 0 ||
+ type != V8_TYPE_JSOBJECT) {
+ mdb_warn("%p is not a JSObject\n", addr);
+ return (WALK_ERR);
+ }
+
+ jspw = mdb_zalloc(sizeof (jsprop_walk_data_t), UM_GC);
+
+ if (jsobj_properties(addr, walk_jsprop_nprops, jspw) == -1) {
+ mdb_warn("couldn't iterate over properties for %p\n", addr);
+ return (WALK_ERR);
+ }
+
+ jspw->jspw_props =
+ mdb_zalloc(jspw->jspw_nprops * sizeof (uintptr_t), UM_GC);
+
+ if (jsobj_properties(addr, walk_jsprop_props, jspw) == -1) {
+ mdb_warn("couldn't iterate over properties for %p\n", addr);
+ return (WALK_ERR);
+ }
+
+ jspw->jspw_current = 0;
+ wsp->walk_data = jspw;
+
+ return (WALK_NEXT);
+}
+
+static int
+walk_jsprop_step(mdb_walk_state_t *wsp)
+{
+ jsprop_walk_data_t *jspw = wsp->walk_data;
+ int rv;
+
+ if (jspw->jspw_current >= jspw->jspw_nprops)
+ return (WALK_DONE);
+
+ if ((rv = wsp->walk_callback(jspw->jspw_props[jspw->jspw_current++],
+ NULL, wsp->walk_cbdata)) != WALK_NEXT)
+ return (rv);
+
+ return (WALK_NEXT);
+}
+
/*
* MDB linkage
*/
@@ -3556,6 +3645,8 @@ static const mdb_dcmd_t v8_mdb_dcmds[] = {
static const mdb_walker_t v8_mdb_walkers[] = {
{ "jsframe", "walk V8 JavaScript stack frames",
walk_jsframes_init, walk_jsframes_step },
+ { "jsprop", "walk property values for an object",
+ walk_jsprop_init, walk_jsprop_step },
{ NULL }
};