diff --git a/configure b/configure index 4ebcc06944..16b36f4f18 100755 --- a/configure +++ b/configure @@ -575,13 +575,6 @@ def configure_node(o): else: o['variables']['node_use_lttng'] = 'false' - # if we're on illumos based systems wrap the helper library into the - # executable - if flavor == 'solaris': - o['variables']['node_use_mdb'] = 'true' - else: - o['variables']['node_use_mdb'] = 'false' - if options.no_ifaddrs: o['defines'] += ['SUNOS_NO_IFADDRS'] diff --git a/deps/mdb_v8/mdb_v8.c b/deps/mdb_v8/mdb_v8.c deleted file mode 100644 index 5653431b8c..0000000000 --- a/deps/mdb_v8/mdb_v8.c +++ /dev/null @@ -1,4603 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * mdb(1M) module for debugging the V8 JavaScript engine. This implementation - * makes heavy use of metadata defined in the V8 binary for inspecting in-memory - * structures. Canned configurations can be manually loaded for V8 binaries - * that predate this metadata. See mdb_v8_cfg.c for details. - * - * NOTE: This dmod implementation (including this file and related headers and C - * files) exist in both the Node and illumos source trees. THESE SHOULD BE KEPT - * IN SYNC. The version in the Node tree is built directly into modern Node - * binaries as part of the build process, and the version in the illumos source - * tree is delivered with the OS for debugging Node binaries that predate - * support for including the dmod directly in the binary. Note too that these - * files have different licenses to match their corresponding repositories. - */ - -/* - * We hard-code our MDB_API_VERSION to be 3 to allow this module to be - * compiled on systems with higher version numbers, but still allow the - * resulting binary object to be used on older systems. (We do not make use - * of functionality present in versions later than 3.) This is particularly - * important for mdb_v8 because (1) it's used in particular to debug - * application-level software and (2) it has a history of rapid evolution. - */ -#define MDB_API_VERSION 3 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v8dbg.h" -#include "v8cfg.h" - -#define offsetof(s, m) ((size_t)(&(((s *)0)->m))) - -/* - * The "v8_class" and "v8_field" structures describe the C++ classes used to - * represent V8 heap objects. - */ -typedef struct v8_class { - struct v8_class *v8c_next; /* list linkage */ - struct v8_class *v8c_parent; /* parent class (inheritance) */ - struct v8_field *v8c_fields; /* array of class fields */ - size_t v8c_start; /* offset of first class field */ - size_t v8c_end; /* offset of first subclass field */ - char v8c_name[64]; /* heap object class name */ -} v8_class_t; - -typedef struct v8_field { - struct v8_field *v8f_next; /* list linkage */ - ssize_t v8f_offset; /* field offset */ - char v8f_name[64]; /* field name */ - boolean_t v8f_isbyte; /* 1-byte int field */ - boolean_t v8f_isstr; /* NUL-terminated string */ -} v8_field_t; - -/* - * Similarly, the "v8_enum" structure describes an enum from V8. - */ -typedef struct { - char v8e_name[64]; - uint_t v8e_value; -} v8_enum_t; - -/* - * During configuration, the dmod updates these globals with the actual set of - * classes, types, and frame types based on the debug metadata. - */ -static v8_class_t *v8_classes; - -static v8_enum_t v8_types[128]; -static int v8_next_type; - -static v8_enum_t v8_frametypes[16]; -static int v8_next_frametype; - -static int v8_warnings; -static int v8_silent; - -/* - * The following constants describe offsets from the frame pointer that are used - * to inspect each stack frame. They're initialized from the debug metadata. - */ -static ssize_t V8_OFF_FP_CONTEXT; -static ssize_t V8_OFF_FP_MARKER; -static ssize_t V8_OFF_FP_FUNCTION; -static ssize_t V8_OFF_FP_ARGS; - -/* - * The following constants are used by macros defined in heap-dbg-common.h to - * examine the types of various V8 heap objects. In general, the macros should - * be preferred to using the constants directly. The values of these constants - * are initialized from the debug metadata. - */ -static intptr_t V8_FirstNonstringType; -static intptr_t V8_IsNotStringMask; -static intptr_t V8_StringTag; -static intptr_t V8_NotStringTag; -static intptr_t V8_StringEncodingMask; -static intptr_t V8_TwoByteStringTag; -static intptr_t V8_AsciiStringTag; -static intptr_t V8_StringRepresentationMask; -static intptr_t V8_SeqStringTag; -static intptr_t V8_ConsStringTag; -static intptr_t V8_SlicedStringTag; -static intptr_t V8_ExternalStringTag; -static intptr_t V8_FailureTag; -static intptr_t V8_FailureTagMask; -static intptr_t V8_HeapObjectTag; -static intptr_t V8_HeapObjectTagMask; -static intptr_t V8_SmiTag; -static intptr_t V8_SmiTagMask; -static intptr_t V8_SmiValueShift; -static intptr_t V8_SmiShiftSize; -static intptr_t V8_PointerSizeLog2; - -static intptr_t V8_ISSHARED_SHIFT; -static intptr_t V8_DICT_SHIFT; -static intptr_t V8_DICT_PREFIX_SIZE; -static intptr_t V8_DICT_ENTRY_SIZE; -static intptr_t V8_DICT_START_INDEX; -static intptr_t V8_PROP_IDX_CONTENT; -static intptr_t V8_PROP_IDX_FIRST; -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_PROP_DESC_KEY; -static intptr_t V8_PROP_DESC_DETAILS; -static intptr_t V8_PROP_DESC_VALUE; -static intptr_t V8_PROP_DESC_SIZE; -static intptr_t V8_TRANSITIONS_IDX_DESC; - -static intptr_t V8_TYPE_JSOBJECT = -1; -static intptr_t V8_TYPE_JSARRAY = -1; -static intptr_t V8_TYPE_FIXEDARRAY = -1; - -static intptr_t V8_ELEMENTS_KIND_SHIFT; -static intptr_t V8_ELEMENTS_KIND_BITCOUNT; -static intptr_t V8_ELEMENTS_FAST_ELEMENTS; -static intptr_t V8_ELEMENTS_FAST_HOLEY_ELEMENTS; -static intptr_t V8_ELEMENTS_DICTIONARY_ELEMENTS; - -/* - * Although we have this information in v8_classes, the following offsets are - * defined explicitly because they're used directly in code below. - */ -static ssize_t V8_OFF_CODE_INSTRUCTION_SIZE; -static ssize_t V8_OFF_CODE_INSTRUCTION_START; -static ssize_t V8_OFF_CONSSTRING_FIRST; -static ssize_t V8_OFF_CONSSTRING_SECOND; -static ssize_t V8_OFF_EXTERNALSTRING_RESOURCE; -static ssize_t V8_OFF_FIXEDARRAY_DATA; -static ssize_t V8_OFF_FIXEDARRAY_LENGTH; -static ssize_t V8_OFF_HEAPNUMBER_VALUE; -static ssize_t V8_OFF_HEAPOBJECT_MAP; -static ssize_t V8_OFF_JSARRAY_LENGTH; -static ssize_t V8_OFF_JSDATE_VALUE; -static ssize_t V8_OFF_JSFUNCTION_SHARED; -static ssize_t V8_OFF_JSOBJECT_ELEMENTS; -static ssize_t V8_OFF_JSOBJECT_PROPERTIES; -static ssize_t V8_OFF_MAP_CONSTRUCTOR; -static ssize_t V8_OFF_MAP_INOBJECT_PROPERTIES; -static ssize_t V8_OFF_MAP_INSTANCE_ATTRIBUTES; -static ssize_t V8_OFF_MAP_INSTANCE_DESCRIPTORS; -static ssize_t V8_OFF_MAP_INSTANCE_SIZE; -static ssize_t V8_OFF_MAP_BIT_FIELD; -static ssize_t V8_OFF_MAP_BIT_FIELD2; -static ssize_t V8_OFF_MAP_BIT_FIELD3; -static ssize_t V8_OFF_MAP_TRANSITIONS; -static ssize_t V8_OFF_ODDBALL_TO_STRING; -static ssize_t V8_OFF_SCRIPT_LINE_ENDS; -static ssize_t V8_OFF_SCRIPT_NAME; -static ssize_t V8_OFF_SCRIPT_SOURCE; -static ssize_t V8_OFF_SEQASCIISTR_CHARS; -static ssize_t V8_OFF_SEQONEBYTESTR_CHARS; -static ssize_t V8_OFF_SEQTWOBYTESTR_CHARS; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_CODE; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_END_POSITION; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_LENGTH; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_SCRIPT; -static ssize_t V8_OFF_SHAREDFUNCTIONINFO_NAME; -static ssize_t V8_OFF_SLICEDSTRING_PARENT; -static ssize_t V8_OFF_SLICEDSTRING_OFFSET; -static ssize_t V8_OFF_STRING_LENGTH; - -#define NODE_OFF_EXTSTR_DATA 0x4 /* see node_string.h */ - -#define V8_CONSTANT_OPTIONAL 1 -#define V8_CONSTANT_HASFALLBACK 2 - -#define V8_CONSTANT_MAJORSHIFT 3 -#define V8_CONSTANT_MAJORMASK ((1 << 4) - 1) -#define V8_CONSTANT_MAJOR(flags) \ - (((flags) >> V8_CONSTANT_MAJORSHIFT) & V8_CONSTANT_MAJORMASK) - -#define V8_CONSTANT_MINORSHIFT 7 -#define V8_CONSTANT_MINORMASK ((1 << 9) - 1) -#define V8_CONSTANT_MINOR(flags) \ - (((flags) >> V8_CONSTANT_MINORSHIFT) & V8_CONSTANT_MINORMASK) - -#define V8_CONSTANT_FALLBACK(maj, min) \ - (V8_CONSTANT_OPTIONAL | V8_CONSTANT_HASFALLBACK | \ - ((maj) << V8_CONSTANT_MAJORSHIFT) | ((min) << V8_CONSTANT_MINORSHIFT)) - -/* - * Table of constants used directly by this file. - */ -typedef struct v8_constant { - intptr_t *v8c_valp; - const char *v8c_symbol; - uint32_t v8c_flags; - intptr_t v8c_fallback; -} v8_constant_t; - -static v8_constant_t v8_constants[] = { - { &V8_OFF_FP_CONTEXT, "v8dbg_off_fp_context" }, - { &V8_OFF_FP_FUNCTION, "v8dbg_off_fp_function" }, - { &V8_OFF_FP_MARKER, "v8dbg_off_fp_marker" }, - { &V8_OFF_FP_ARGS, "v8dbg_off_fp_args" }, - - { &V8_FirstNonstringType, "v8dbg_FirstNonstringType" }, - { &V8_IsNotStringMask, "v8dbg_IsNotStringMask" }, - { &V8_StringTag, "v8dbg_StringTag" }, - { &V8_NotStringTag, "v8dbg_NotStringTag" }, - { &V8_StringEncodingMask, "v8dbg_StringEncodingMask" }, - { &V8_TwoByteStringTag, "v8dbg_TwoByteStringTag" }, - { &V8_AsciiStringTag, "v8dbg_AsciiStringTag" }, - { &V8_StringRepresentationMask, "v8dbg_StringRepresentationMask" }, - { &V8_SeqStringTag, "v8dbg_SeqStringTag" }, - { &V8_ConsStringTag, "v8dbg_ConsStringTag" }, - { &V8_SlicedStringTag, "v8dbg_SlicedStringTag", - V8_CONSTANT_FALLBACK(0, 0), 0x3 }, - { &V8_ExternalStringTag, "v8dbg_ExternalStringTag" }, - { &V8_FailureTag, "v8dbg_FailureTag" }, - { &V8_FailureTagMask, "v8dbg_FailureTagMask" }, - { &V8_HeapObjectTag, "v8dbg_HeapObjectTag" }, - { &V8_HeapObjectTagMask, "v8dbg_HeapObjectTagMask" }, - { &V8_SmiTag, "v8dbg_SmiTag" }, - { &V8_SmiTagMask, "v8dbg_SmiTagMask" }, - { &V8_SmiValueShift, "v8dbg_SmiValueShift" }, - { &V8_SmiShiftSize, "v8dbg_SmiShiftSize", -#ifdef _LP64 - V8_CONSTANT_FALLBACK(0, 0), 31 }, -#else - V8_CONSTANT_FALLBACK(0, 0), 0 }, -#endif - { &V8_PointerSizeLog2, "v8dbg_PointerSizeLog2" }, - - { &V8_DICT_SHIFT, "v8dbg_dict_shift", - V8_CONSTANT_FALLBACK(3, 13), 24 }, - { &V8_DICT_PREFIX_SIZE, "v8dbg_dict_prefix_size", - V8_CONSTANT_FALLBACK(3, 11), 2 }, - { &V8_DICT_ENTRY_SIZE, "v8dbg_dict_entry_size", - V8_CONSTANT_FALLBACK(3, 11), 3 }, - { &V8_DICT_START_INDEX, "v8dbg_dict_start_index", - V8_CONSTANT_FALLBACK(3, 11), 3 }, - { &V8_ISSHARED_SHIFT, "v8dbg_isshared_shift", - V8_CONSTANT_FALLBACK(3, 11), 0 }, - { &V8_PROP_IDX_FIRST, "v8dbg_prop_idx_first" }, - { &V8_PROP_TYPE_FIELD, "v8dbg_prop_type_field" }, - { &V8_PROP_FIRST_PHANTOM, "v8dbg_prop_type_first_phantom" }, - { &V8_PROP_TYPE_MASK, "v8dbg_prop_type_mask" }, - { &V8_PROP_IDX_CONTENT, "v8dbg_prop_idx_content", - V8_CONSTANT_OPTIONAL }, - { &V8_PROP_DESC_KEY, "v8dbg_prop_desc_key", - V8_CONSTANT_FALLBACK(0, 0), 0 }, - { &V8_PROP_DESC_DETAILS, "v8dbg_prop_desc_details", - V8_CONSTANT_FALLBACK(0, 0), 1 }, - { &V8_PROP_DESC_VALUE, "v8dbg_prop_desc_value", - V8_CONSTANT_FALLBACK(0, 0), 2 }, - { &V8_PROP_DESC_SIZE, "v8dbg_prop_desc_size", - V8_CONSTANT_FALLBACK(0, 0), 3 }, - { &V8_TRANSITIONS_IDX_DESC, "v8dbg_transitions_idx_descriptors", - V8_CONSTANT_OPTIONAL }, - - { &V8_ELEMENTS_KIND_SHIFT, "v8dbg_elements_kind_shift", - V8_CONSTANT_FALLBACK(0, 0), 3 }, - { &V8_ELEMENTS_KIND_BITCOUNT, "v8dbg_elements_kind_bitcount", - V8_CONSTANT_FALLBACK(0, 0), 5 }, - { &V8_ELEMENTS_FAST_ELEMENTS, - "v8dbg_elements_fast_elements", - V8_CONSTANT_FALLBACK(0, 0), 2 }, - { &V8_ELEMENTS_FAST_HOLEY_ELEMENTS, - "v8dbg_elements_fast_holey_elements", - V8_CONSTANT_FALLBACK(0, 0), 3 }, - { &V8_ELEMENTS_DICTIONARY_ELEMENTS, - "v8dbg_elements_dictionary_elements", - V8_CONSTANT_FALLBACK(0, 0), 6 }, -}; - -static int v8_nconstants = sizeof (v8_constants) / sizeof (v8_constants[0]); - -typedef struct v8_offset { - ssize_t *v8o_valp; - const char *v8o_class; - const char *v8o_member; - boolean_t v8o_optional; -} v8_offset_t; - -static v8_offset_t v8_offsets[] = { - { &V8_OFF_CODE_INSTRUCTION_SIZE, - "Code", "instruction_size" }, - { &V8_OFF_CODE_INSTRUCTION_START, - "Code", "instruction_start" }, - { &V8_OFF_CONSSTRING_FIRST, - "ConsString", "first" }, - { &V8_OFF_CONSSTRING_SECOND, - "ConsString", "second" }, - { &V8_OFF_EXTERNALSTRING_RESOURCE, - "ExternalString", "resource" }, - { &V8_OFF_FIXEDARRAY_DATA, - "FixedArray", "data" }, - { &V8_OFF_FIXEDARRAY_LENGTH, - "FixedArray", "length" }, - { &V8_OFF_HEAPNUMBER_VALUE, - "HeapNumber", "value" }, - { &V8_OFF_HEAPOBJECT_MAP, - "HeapObject", "map" }, - { &V8_OFF_JSARRAY_LENGTH, - "JSArray", "length" }, - { &V8_OFF_JSDATE_VALUE, - "JSDate", "value", B_TRUE }, - { &V8_OFF_JSFUNCTION_SHARED, - "JSFunction", "shared" }, - { &V8_OFF_JSOBJECT_ELEMENTS, - "JSObject", "elements" }, - { &V8_OFF_JSOBJECT_PROPERTIES, - "JSObject", "properties" }, - { &V8_OFF_MAP_CONSTRUCTOR, - "Map", "constructor" }, - { &V8_OFF_MAP_INOBJECT_PROPERTIES, - "Map", "inobject_properties" }, - { &V8_OFF_MAP_INSTANCE_ATTRIBUTES, - "Map", "instance_attributes" }, - { &V8_OFF_MAP_INSTANCE_DESCRIPTORS, - "Map", "instance_descriptors", B_TRUE }, - { &V8_OFF_MAP_TRANSITIONS, - "Map", "transitions", B_TRUE }, - { &V8_OFF_MAP_INSTANCE_SIZE, - "Map", "instance_size" }, - { &V8_OFF_MAP_BIT_FIELD2, - "Map", "bit_field2", B_TRUE }, - { &V8_OFF_MAP_BIT_FIELD3, - "Map", "bit_field3", B_TRUE }, - { &V8_OFF_ODDBALL_TO_STRING, - "Oddball", "to_string" }, - { &V8_OFF_SCRIPT_LINE_ENDS, - "Script", "line_ends" }, - { &V8_OFF_SCRIPT_NAME, - "Script", "name" }, - { &V8_OFF_SCRIPT_SOURCE, - "Script", "source" }, - { &V8_OFF_SEQASCIISTR_CHARS, - "SeqAsciiString", "chars", B_TRUE }, - { &V8_OFF_SEQONEBYTESTR_CHARS, - "SeqOneByteString", "chars", B_TRUE }, - { &V8_OFF_SEQTWOBYTESTR_CHARS, - "SeqTwoByteString", "chars", B_TRUE }, - { &V8_OFF_SHAREDFUNCTIONINFO_CODE, - "SharedFunctionInfo", "code" }, - { &V8_OFF_SHAREDFUNCTIONINFO_END_POSITION, - "SharedFunctionInfo", "end_position" }, - { &V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION, - "SharedFunctionInfo", "function_token_position" }, - { &V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME, - "SharedFunctionInfo", "inferred_name" }, - { &V8_OFF_SHAREDFUNCTIONINFO_LENGTH, - "SharedFunctionInfo", "length" }, - { &V8_OFF_SHAREDFUNCTIONINFO_NAME, - "SharedFunctionInfo", "name" }, - { &V8_OFF_SHAREDFUNCTIONINFO_SCRIPT, - "SharedFunctionInfo", "script" }, - { &V8_OFF_SLICEDSTRING_OFFSET, - "SlicedString", "offset" }, - { &V8_OFF_SLICEDSTRING_PARENT, - "SlicedString", "parent", B_TRUE }, - { &V8_OFF_STRING_LENGTH, - "String", "length" }, -}; - -static int v8_noffsets = sizeof (v8_offsets) / sizeof (v8_offsets[0]); - -static uintptr_t v8_major; -static uintptr_t v8_minor; -static uintptr_t v8_build; -static uintptr_t v8_patch; - -static int autoconf_iter_symbol(mdb_symbol_t *, void *); -static v8_class_t *conf_class_findcreate(const char *); -static v8_field_t *conf_field_create(v8_class_t *, const char *, size_t); -static char *conf_next_part(char *, char *); -static int conf_update_parent(const char *); -static int conf_update_field(v8_cfg_t *, const char *); -static int conf_update_enum(v8_cfg_t *, const char *, const char *, - v8_enum_t *); -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 *); - -/* - * Invoked when this dmod is initially loaded to load the set of classes, enums, - * and other constants from the metadata in the target binary. - */ -static int -autoconfigure(v8_cfg_t *cfgp) -{ - v8_class_t *clp; - v8_enum_t *ep; - struct v8_constant *cnp; - int ii; - int failed = 0; - - assert(v8_classes == NULL); - - /* - * Iterate all global symbols looking for metadata. - */ - if (cfgp->v8cfg_iter(cfgp, autoconf_iter_symbol, cfgp) != 0) { - mdb_warn("failed to autoconfigure V8 support\n"); - return (-1); - } - - /* - * By now we've configured all of the classes so we can update the - * "start" and "end" fields in each class with information from its - * parent class. - */ - for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { - if (clp->v8c_end != (size_t)-1) - continue; - - conf_class_compute_offsets(clp); - }; - - /* - * Load various constants used directly in the module. - */ - for (ii = 0; ii < v8_nconstants; ii++) { - cnp = &v8_constants[ii]; - - if (cfgp->v8cfg_readsym(cfgp, - cnp->v8c_symbol, cnp->v8c_valp) != -1) { - continue; - } - - if (!(cnp->v8c_flags & V8_CONSTANT_OPTIONAL)) { - mdb_warn("failed to read \"%s\"", cnp->v8c_symbol); - failed++; - continue; - } - - if (!(cnp->v8c_flags & V8_CONSTANT_HASFALLBACK) || - v8_major < V8_CONSTANT_MAJOR(cnp->v8c_flags) || - (v8_major == V8_CONSTANT_MAJOR(cnp->v8c_flags) && - v8_minor < V8_CONSTANT_MINOR(cnp->v8c_flags))) { - *cnp->v8c_valp = -1; - continue; - } - - /* - * We have a fallback -- and we know that the version satisfies - * the fallback's version constraints; use the fallback value. - */ - *cnp->v8c_valp = cnp->v8c_fallback; - } - - /* - * 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, "JSArray") == 0) - V8_TYPE_JSARRAY = ep->v8e_value; - - if (strcmp(ep->v8e_name, "FixedArray") == 0) - V8_TYPE_FIXEDARRAY = ep->v8e_value; - } - - if (V8_TYPE_JSOBJECT == -1) { - mdb_warn("couldn't find JSObject type\n"); - failed++; - } - - if (V8_TYPE_JSARRAY == -1) { - mdb_warn("couldn't find JSArray type\n"); - failed++; - } - - if (V8_TYPE_FIXEDARRAY == -1) { - mdb_warn("couldn't find FixedArray type\n"); - failed++; - } - - /* - * Finally, load various class offsets. - */ - for (ii = 0; ii < v8_noffsets; ii++) { - struct v8_offset *offp = &v8_offsets[ii]; - const char *klass = offp->v8o_class; - -again: - if (heap_offset(klass, offp->v8o_member, offp->v8o_valp) == 0) - continue; - - if (strcmp(klass, "FixedArray") == 0) { - /* - * The V8 included in node v0.6 uses a FixedArrayBase - * class to contain the "length" field, while the one - * in v0.4 has no such base class and stores the field - * directly in FixedArray; if we failed to derive - * the offset from FixedArray, try FixedArrayBase. - */ - klass = "FixedArrayBase"; - goto again; - } - - if (offp->v8o_optional) { - *offp->v8o_valp = -1; - continue; - } - - mdb_warn("couldn't find class \"%s\", field \"%s\"\n", - offp->v8o_class, offp->v8o_member); - failed++; - } - - if (!((V8_OFF_SEQASCIISTR_CHARS != -1) ^ - (V8_OFF_SEQONEBYTESTR_CHARS != -1))) { - mdb_warn("expected exactly one of SeqAsciiString and " - "SeqOneByteString to be defined\n"); - failed++; - } - - if (V8_OFF_SEQONEBYTESTR_CHARS != -1) - V8_OFF_SEQASCIISTR_CHARS = V8_OFF_SEQONEBYTESTR_CHARS; - - if (V8_OFF_SEQTWOBYTESTR_CHARS == -1) - V8_OFF_SEQTWOBYTESTR_CHARS = V8_OFF_SEQASCIISTR_CHARS; - - if (V8_OFF_SLICEDSTRING_PARENT == -1) - V8_OFF_SLICEDSTRING_PARENT = V8_OFF_SLICEDSTRING_OFFSET - - sizeof (uintptr_t); - - /* - * If we don't have bit_field/bit_field2 for Map, we know that they're - * the second and third byte of instance_attributes. - */ - if (V8_OFF_MAP_BIT_FIELD == -1) - V8_OFF_MAP_BIT_FIELD = V8_OFF_MAP_INSTANCE_ATTRIBUTES + 2; - - if (V8_OFF_MAP_BIT_FIELD2 == -1) - V8_OFF_MAP_BIT_FIELD2 = V8_OFF_MAP_INSTANCE_ATTRIBUTES + 3; - - return (failed ? -1 : 0); -} - -/* ARGSUSED */ -static int -autoconf_iter_symbol(mdb_symbol_t *symp, void *arg) -{ - v8_cfg_t *cfgp = arg; - - if (strncmp(symp->sym_name, "v8dbg_parent_", - sizeof ("v8dbg_parent_") - 1) == 0) - return (conf_update_parent(symp->sym_name)); - - if (strncmp(symp->sym_name, "v8dbg_class_", - sizeof ("v8dbg_class_") - 1) == 0) - return (conf_update_field(cfgp, symp->sym_name)); - - if (strncmp(symp->sym_name, "v8dbg_type_", - sizeof ("v8dbg_type_") - 1) == 0) - return (conf_update_type(cfgp, symp->sym_name)); - - if (strncmp(symp->sym_name, "v8dbg_frametype_", - sizeof ("v8dbg_frametype_") - 1) == 0) - return (conf_update_frametype(cfgp, symp->sym_name)); - - return (0); -} - -/* - * Extracts the next field of a string whose fields are separated by "__" (as - * the V8 metadata symbols are). - */ -static char * -conf_next_part(char *buf, char *start) -{ - char *pp; - - if ((pp = strstr(start, "__")) == NULL) { - mdb_warn("malformed symbol name: %s\n", buf); - return (NULL); - } - - *pp = '\0'; - return (pp + sizeof ("__") - 1); -} - -static v8_class_t * -conf_class_findcreate(const char *name) -{ - v8_class_t *clp, *iclp, *prev = NULL; - int cmp; - - for (iclp = v8_classes; iclp != NULL; iclp = iclp->v8c_next) { - if ((cmp = strcmp(iclp->v8c_name, name)) == 0) - return (iclp); - - if (cmp > 0) - break; - - prev = iclp; - } - - if ((clp = mdb_zalloc(sizeof (*clp), UM_NOSLEEP)) == NULL) - return (NULL); - - (void) strlcpy(clp->v8c_name, name, sizeof (clp->v8c_name)); - clp->v8c_end = (size_t)-1; - clp->v8c_next = iclp; - - if (prev != NULL) { - prev->v8c_next = clp; - } else { - v8_classes = clp; - } - - return (clp); -} - -static v8_field_t * -conf_field_create(v8_class_t *clp, const char *name, size_t offset) -{ - v8_field_t *flp, *iflp; - - if ((flp = mdb_zalloc(sizeof (*flp), UM_NOSLEEP)) == NULL) - return (NULL); - - (void) strlcpy(flp->v8f_name, name, sizeof (flp->v8f_name)); - flp->v8f_offset = offset; - - if (clp->v8c_fields == NULL || clp->v8c_fields->v8f_offset > offset) { - flp->v8f_next = clp->v8c_fields; - clp->v8c_fields = flp; - return (flp); - } - - for (iflp = clp->v8c_fields; iflp->v8f_next != NULL; - iflp = iflp->v8f_next) { - if (iflp->v8f_next->v8f_offset > offset) - break; - } - - flp->v8f_next = iflp->v8f_next; - iflp->v8f_next = flp; - return (flp); -} - -/* - * Given a "v8dbg_parent_X__Y", symbol, update the parent of class X to class Y. - * Note that neither class necessarily exists already. - */ -static int -conf_update_parent(const char *symbol) -{ - char *pp, *qq; - char buf[128]; - v8_class_t *clp, *pclp; - - (void) strlcpy(buf, symbol, sizeof (buf)); - pp = buf + sizeof ("v8dbg_parent_") - 1; - qq = conf_next_part(buf, pp); - - if (qq == NULL) - return (-1); - - clp = conf_class_findcreate(pp); - pclp = conf_class_findcreate(qq); - - if (clp == NULL || pclp == NULL) { - mdb_warn("mdb_v8: out of memory\n"); - return (-1); - } - - clp->v8c_parent = pclp; - return (0); -} - -/* - * Given a "v8dbg_class_CLASS__FIELD__TYPE", symbol, save field "FIELD" into - * class CLASS with the offset described by the symbol. Note that CLASS does - * not necessarily exist already. - */ -static int -conf_update_field(v8_cfg_t *cfgp, const char *symbol) -{ - v8_class_t *clp; - v8_field_t *flp; - intptr_t offset; - char *pp, *qq, *tt; - char buf[128]; - - (void) strlcpy(buf, symbol, sizeof (buf)); - - pp = buf + sizeof ("v8dbg_class_") - 1; - qq = conf_next_part(buf, pp); - - if (qq == NULL || (tt = conf_next_part(buf, qq)) == NULL) - return (-1); - - if (cfgp->v8cfg_readsym(cfgp, symbol, &offset) == -1) { - mdb_warn("failed to read symbol \"%s\"", symbol); - return (-1); - } - - if ((clp = conf_class_findcreate(pp)) == NULL || - (flp = conf_field_create(clp, qq, (size_t)offset)) == NULL) - return (-1); - - if (strcmp(tt, "int") == 0) - flp->v8f_isbyte = B_TRUE; - - if (strcmp(tt, "char") == 0) - flp->v8f_isstr = B_TRUE; - - return (0); -} - -static int -conf_update_enum(v8_cfg_t *cfgp, const char *symbol, const char *name, - v8_enum_t *enp) -{ - intptr_t value; - - if (cfgp->v8cfg_readsym(cfgp, symbol, &value) == -1) { - mdb_warn("failed to read symbol \"%s\"", symbol); - return (-1); - } - - enp->v8e_value = (int)value; - (void) strlcpy(enp->v8e_name, name, sizeof (enp->v8e_name)); - return (0); -} - -/* - * Given a "v8dbg_type_TYPENAME" constant, save the type name in v8_types. Note - * that this enum has multiple integer values with the same string label. - */ -static int -conf_update_type(v8_cfg_t *cfgp, const char *symbol) -{ - char *klass; - v8_enum_t *enp; - char buf[128]; - - if (v8_next_type > sizeof (v8_types) / sizeof (v8_types[0])) { - mdb_warn("too many V8 types\n"); - return (-1); - } - - (void) strlcpy(buf, symbol, sizeof (buf)); - - klass = buf + sizeof ("v8dbg_type_") - 1; - if (conf_next_part(buf, klass) == NULL) - return (-1); - - enp = &v8_types[v8_next_type++]; - return (conf_update_enum(cfgp, symbol, klass, enp)); -} - -/* - * Given a "v8dbg_frametype_TYPENAME" constant, save the frame type in - * v8_frametypes. - */ -static int -conf_update_frametype(v8_cfg_t *cfgp, const char *symbol) -{ - const char *frametype; - v8_enum_t *enp; - - if (v8_next_frametype > - sizeof (v8_frametypes) / sizeof (v8_frametypes[0])) { - mdb_warn("too many V8 frame types\n"); - return (-1); - } - - enp = &v8_frametypes[v8_next_frametype++]; - frametype = symbol + sizeof ("v8dbg_frametype_") - 1; - return (conf_update_enum(cfgp, symbol, frametype, enp)); -} - -/* - * Now that all classes have been loaded, update the "start" and "end" fields of - * each class based on the values of its parent class. - */ -static void -conf_class_compute_offsets(v8_class_t *clp) -{ - v8_field_t *flp; - - assert(clp->v8c_start == 0); - assert(clp->v8c_end == (size_t)-1); - - if (clp->v8c_parent != NULL) { - if (clp->v8c_parent->v8c_end == (size_t)-1) - conf_class_compute_offsets(clp->v8c_parent); - - clp->v8c_start = clp->v8c_parent->v8c_end; - } - - if (clp->v8c_fields == NULL) { - clp->v8c_end = clp->v8c_start; - return; - } - - for (flp = clp->v8c_fields; flp->v8f_next != NULL; flp = flp->v8f_next) - ; - - if (flp == NULL) - clp->v8c_end = clp->v8c_start; - else - clp->v8c_end = flp->v8f_offset + sizeof (uintptr_t); -} - -/* - * Utility functions - */ -#define JSSTR_NONE 0 -#define JSSTR_NUDE JSSTR_NONE - -#define JSSTR_FLAGSHIFT 16 -#define JSSTR_VERBOSE (0x1 << JSSTR_FLAGSHIFT) -#define JSSTR_QUOTED (0x2 << JSSTR_FLAGSHIFT) -#define JSSTR_ISASCII (0x4 << JSSTR_FLAGSHIFT) - -#define JSSTR_MAXDEPTH 512 -#define JSSTR_DEPTH(f) ((f) & ((1 << JSSTR_FLAGSHIFT) - 1)) -#define JSSTR_BUMPDEPTH(f) ((f) + 1) - -static int jsstr_print(uintptr_t, uint_t, char **, size_t *); -static boolean_t jsobj_is_undefined(uintptr_t addr); -static boolean_t jsobj_is_hole(uintptr_t addr); - -static const char * -enum_lookup_str(v8_enum_t *enums, int val, const char *dflt) -{ - v8_enum_t *ep; - - for (ep = enums; ep->v8e_name[0] != '\0'; ep++) { - if (ep->v8e_value == val) - return (ep->v8e_name); - } - - return (dflt); -} - -static void -enum_print(v8_enum_t *enums) -{ - v8_enum_t *itp; - - for (itp = enums; itp->v8e_name[0] != '\0'; itp++) - mdb_printf("%-30s = 0x%02x\n", itp->v8e_name, itp->v8e_value); -} - -/* - * b[v]snprintf behave like [v]snprintf(3c), except that they update the buffer - * and length arguments based on how much buffer space is used by the operation. - * This makes it much easier to combine multiple calls in sequence without - * worrying about buffer overflow. - */ -static size_t -bvsnprintf(char **bufp, size_t *buflenp, const char *format, va_list alist) -{ - size_t rv, len; - - if (*buflenp == 0) - return (vsnprintf(NULL, 0, format, alist)); - - rv = vsnprintf(*bufp, *buflenp, format, alist); - - len = MIN(rv, *buflenp); - *buflenp -= len; - *bufp += len; - - return (len); -} - -static size_t -bsnprintf(char **bufp, size_t *buflenp, const char *format, ...) -{ - va_list alist; - size_t rv; - - va_start(alist, format); - rv = bvsnprintf(bufp, buflenp, format, alist); - va_end(alist); - - return (rv); -} - -static void -v8_warn(const char *format, ...) -{ - char buf[512]; - va_list alist; - int len; - - if (!v8_warnings || v8_silent) - return; - - va_start(alist, format); - (void) vsnprintf(buf, sizeof (buf), format, alist); - va_end(alist); - - /* - * This is made slightly annoying because we need to effectively - * preserve the original format string to allow for mdb to use the - * new-line at the end to indicate that strerror should be elided. - */ - if ((len = strlen(format)) > 0 && format[len - 1] == '\n') { - buf[strlen(buf) - 1] = '\0'; - mdb_warn("%s\n", buf); - } else { - mdb_warn("%s", buf); - } -} - -/* - * Returns in "offp" the offset of field "field" in C++ class "klass". - */ -static int -heap_offset(const char *klass, const char *field, ssize_t *offp) -{ - v8_class_t *clp; - v8_field_t *flp; - - for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { - if (strcmp(klass, clp->v8c_name) == 0) - break; - } - - if (clp == NULL) - return (-1); - - for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) { - if (strcmp(field, flp->v8f_name) == 0) - break; - } - - if (flp == NULL) - return (-1); - - *offp = V8_OFF_HEAP(flp->v8f_offset); - return (0); -} - -/* - * Assuming "addr" is an instance of the C++ heap class "klass", read into *valp - * the pointer-sized value of field "field". - */ -static int -read_heap_ptr(uintptr_t *valp, uintptr_t addr, ssize_t off) -{ - if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { - v8_warn("failed to read offset %d from %p", off, addr); - return (-1); - } - - return (0); -} - -/* - * Like read_heap_ptr, but assume the field is an SMI and store the actual value - * into *valp rather than the encoded representation. - */ -static int -read_heap_smi(uintptr_t *valp, uintptr_t addr, ssize_t off) -{ - if (read_heap_ptr(valp, addr, off) != 0) - return (-1); - - if (!V8_IS_SMI(*valp)) { - v8_warn("expected SMI, got %p\n", *valp); - return (-1); - } - - *valp = V8_SMI_VALUE(*valp); - - return (0); -} - -static int -read_heap_double(double *valp, uintptr_t addr, ssize_t off) -{ - if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { - v8_warn("failed to read heap value at %p", addr + off); - return (-1); - } - - return (0); -} - -/* - * Assuming "addr" refers to a FixedArray, return a newly-allocated array - * representing its contents. - */ -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); - - *lenp = len; - - if (len == 0) { - *retp = NULL; - return (0); - } - - if ((*retp = mdb_zalloc(len * sizeof (uintptr_t), flags)) == NULL) - return (-1); - - if (mdb_vread(*retp, len * sizeof (uintptr_t), - addr + V8_OFF_FIXEDARRAY_DATA) == -1) { - if (!(flags & UM_GC)) - mdb_free(*retp, len * sizeof (uintptr_t)); - - *retp = NULL; - return (-1); - } - - return (0); -} - -static int -read_heap_byte(uint8_t *valp, uintptr_t addr, ssize_t off) -{ - if (mdb_vread(valp, sizeof (*valp), addr + off) == -1) { - v8_warn("failed to read heap value at %p", addr + off); - return (-1); - } - - return (0); -} - -/* - * Given a heap object, returns in *valp the byte describing the type of the - * object. This is shorthand for first retrieving the Map at the start of the - * heap object and then retrieving the type byte from the Map object. - */ -static int -read_typebyte(uint8_t *valp, uintptr_t addr) -{ - uintptr_t mapaddr; - ssize_t off = V8_OFF_HEAPOBJECT_MAP; - - if (mdb_vread(&mapaddr, sizeof (mapaddr), addr + off) == -1) { - v8_warn("failed to read type of %p", addr); - return (-1); - } - - if (!V8_IS_HEAPOBJECT(mapaddr)) { - v8_warn("object map is not a heap object\n"); - return (-1); - } - - if (read_heap_byte(valp, mapaddr, V8_OFF_MAP_INSTANCE_ATTRIBUTES) == -1) - return (-1); - - return (0); -} - -/* - * Given a heap object, returns in *valp the size of the object. For - * variable-size objects, returns an undefined value. - */ -static int -read_size(size_t *valp, uintptr_t addr) -{ - uintptr_t mapaddr; - uint8_t size; - - if (read_heap_ptr(&mapaddr, addr, V8_OFF_HEAPOBJECT_MAP) != 0) - return (-1); - - if (!V8_IS_HEAPOBJECT(mapaddr)) { - v8_warn("heap object map is not itself a heap object\n"); - return (-1); - } - - if (read_heap_byte(&size, mapaddr, V8_OFF_MAP_INSTANCE_SIZE) != 0) - return (-1); - - *valp = size << V8_PointerSizeLog2; - return (0); -} - -/* - * Assuming "addr" refers to a FixedArray that is implementing a - * StringDictionary, iterate over its contents calling the specified function - * with key and value. - */ -static int -read_heap_dict(uintptr_t addr, - int (*func)(const char *, uintptr_t, void *), void *arg) -{ - uint8_t type; - uintptr_t len; - char buf[512]; - char *bufp; - int rval = -1; - uintptr_t *dict, ndict, i; - - if (read_heap_array(addr, &dict, &ndict, UM_SLEEP) != 0) - return (-1); - - if (V8_DICT_ENTRY_SIZE < 2) { - v8_warn("dictionary entry size (%d) is too small for a " - "key and value\n", V8_DICT_ENTRY_SIZE); - goto out; - } - - for (i = V8_DICT_START_INDEX + V8_DICT_PREFIX_SIZE; i < ndict; - i += V8_DICT_ENTRY_SIZE) { - /* - * The layout here is key, value, details. (This is hardcoded - * in Dictionary::SetEntry().) - */ - if (jsobj_is_undefined(dict[i])) - continue; - - if (V8_IS_SMI(dict[i])) { - intptr_t val = V8_SMI_VALUE(dict[i]); - - (void) snprintf(buf, sizeof (buf), "%ld", val); - } else { - if (jsobj_is_hole(dict[i])) { - /* - * In some cases, the key can (apparently) be a - * hole, in which case we skip over it. - */ - continue; - } - - if (read_typebyte(&type, dict[i]) != 0) - goto out; - - if (!V8_TYPE_STRING(type)) - goto out; - - bufp = buf; - len = sizeof (buf); - - if (jsstr_print(dict[i], JSSTR_NUDE, &bufp, &len) != 0) - goto out; - } - - if (func(buf, dict[i + 1], arg) == -1) - goto out; - } - - rval = 0; -out: - mdb_free(dict, ndict * sizeof (uintptr_t)); - - return (rval); -} - -/* - * Returns in "buf" a description of the type of "addr" suitable for printing. - */ -static int -obj_jstype(uintptr_t addr, char **bufp, size_t *lenp, uint8_t *typep) -{ - uint8_t typebyte; - uintptr_t strptr; - const char *typename; - - if (V8_IS_FAILURE(addr)) { - if (typep) - *typep = 0; - (void) bsnprintf(bufp, lenp, "'Failure' object"); - return (0); - } - - if (V8_IS_SMI(addr)) { - if (typep) - *typep = 0; - (void) bsnprintf(bufp, lenp, "SMI: value = %d", - V8_SMI_VALUE(addr)); - return (0); - } - - if (read_typebyte(&typebyte, addr) != 0) - return (-1); - - if (typep) - *typep = typebyte; - - typename = enum_lookup_str(v8_types, typebyte, ""); - (void) bsnprintf(bufp, lenp, typename); - - if (strcmp(typename, "Oddball") == 0) { - if (read_heap_ptr(&strptr, addr, - V8_OFF_ODDBALL_TO_STRING) != -1) { - (void) bsnprintf(bufp, lenp, ": \""); - (void) jsstr_print(strptr, JSSTR_NUDE, bufp, lenp); - (void) bsnprintf(bufp, lenp, "\""); - } - } - - return (0); -} - -/* - * Print out the fields of the given object that come from the given class. - */ -static int -obj_print_fields(uintptr_t baddr, v8_class_t *clp) -{ - v8_field_t *flp; - uintptr_t addr, value; - int rv; - char *bufp; - size_t len; - uint8_t type; - char buf[256]; - - for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) { - bufp = buf; - len = sizeof (buf); - - addr = baddr + V8_OFF_HEAP(flp->v8f_offset); - - if (flp->v8f_isstr) { - if (mdb_readstr(buf, sizeof (buf), addr) == -1) { - mdb_printf("%p %s (unreadable)\n", - addr, flp->v8f_name); - continue; - } - - mdb_printf("%p %s = \"%s\"\n", - addr, flp->v8f_name, buf); - continue; - } - - if (flp->v8f_isbyte) { - uint8_t sv; - if (mdb_vread(&sv, sizeof (sv), addr) == -1) { - mdb_printf("%p %s (unreadable)\n", - addr, flp->v8f_name); - continue; - } - - mdb_printf("%p %s = 0x%x\n", addr, flp->v8f_name, sv); - continue; - } - - rv = mdb_vread((void *)&value, sizeof (value), addr); - - if (rv != sizeof (value) || - obj_jstype(value, &bufp, &len, &type) != 0) { - mdb_printf("%p %s (unreadable)\n", addr, flp->v8f_name); - continue; - } - - if (type != 0 && V8_TYPE_STRING(type)) { - (void) bsnprintf(&bufp, &len, ": "); - (void) jsstr_print(value, JSSTR_QUOTED, &bufp, &len); - } - - mdb_printf("%p %s = %p (%s)\n", addr, flp->v8f_name, value, - buf); - } - - return (DCMD_OK); -} - -/* - * Print out all fields of the given object, starting with the root of the class - * hierarchy and working down the most specific type. - */ -static int -obj_print_class(uintptr_t addr, v8_class_t *clp) -{ - int rv = 0; - - /* - * If we have no fields, we just print a simple inheritance hierarchy. - * If we have fields but our parent doesn't, our header includes the - * inheritance hierarchy. - */ - if (clp->v8c_end == 0) { - mdb_printf("%s ", clp->v8c_name); - - if (clp->v8c_parent != NULL) { - mdb_printf("< "); - (void) obj_print_class(addr, clp->v8c_parent); - } - - return (0); - } - - mdb_printf("%p %s", addr, clp->v8c_name); - - if (clp->v8c_start == 0 && clp->v8c_parent != NULL) { - mdb_printf(" < "); - (void) obj_print_class(addr, clp->v8c_parent); - } - - mdb_printf(" {\n"); - (void) mdb_inc_indent(4); - - if (clp->v8c_start > 0 && clp->v8c_parent != NULL) - rv = obj_print_class(addr, clp->v8c_parent); - - rv |= obj_print_fields(addr, clp); - (void) mdb_dec_indent(4); - mdb_printf("}\n"); - - return (rv); -} - -/* - * Print the ASCII string for the given JS string, expanding ConsStrings and - * ExternalStrings as needed. - */ -static int jsstr_print_seq(uintptr_t, uint_t, char **, size_t *, size_t, - ssize_t); -static int jsstr_print_cons(uintptr_t, uint_t, char **, size_t *); -static int jsstr_print_sliced(uintptr_t, uint_t, char **, size_t *); -static int jsstr_print_external(uintptr_t, uint_t, char **, size_t *); - -static int -jsstr_print(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) -{ - uint8_t typebyte; - int err = 0; - char *lbufp; - size_t llen; - char buf[64]; - boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; - - if (read_typebyte(&typebyte, addr) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (!V8_TYPE_STRING(typebyte)) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (verbose) { - lbufp = buf; - llen = sizeof (buf); - (void) obj_jstype(addr, &lbufp, &llen, NULL); - mdb_printf("%s\n", buf); - (void) mdb_inc_indent(4); - } - - if (JSSTR_DEPTH(flags) > JSSTR_MAXDEPTH) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (V8_STRENC_ASCII(typebyte)) - flags |= JSSTR_ISASCII; - else - flags &= ~JSSTR_ISASCII; - - flags = JSSTR_BUMPDEPTH(flags); - - if (V8_STRREP_SEQ(typebyte)) - err = jsstr_print_seq(addr, flags, bufp, lenp, 0, -1); - else if (V8_STRREP_CONS(typebyte)) - err = jsstr_print_cons(addr, flags, bufp, lenp); - else if (V8_STRREP_EXT(typebyte)) - err = jsstr_print_external(addr, flags, bufp, lenp); - else if (V8_STRREP_SLICED(typebyte)) - err = jsstr_print_sliced(addr, flags, bufp, lenp); - else { - (void) bsnprintf(bufp, lenp, ""); - err = -1; - } - - if (verbose) - (void) mdb_dec_indent(4); - - return (err); -} - -static int -jsstr_print_seq(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp, - size_t sliceoffset, ssize_t slicelen) -{ - /* - * To allow the caller to allocate a very large buffer for strings, - * we'll allocate a buffer sized based on our input, making it at - * least enough space for our ellipsis and at most 256K. - */ - uintptr_t i, nreadoffset, blen, nstrbytes, nstrchrs; - ssize_t nreadbytes; - boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; - boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; - char *buf; - uint16_t chrval; - - if ((blen = MIN(*lenp, 256 * 1024)) == 0) - return (0); - - buf = alloca(blen); - - if (read_heap_smi(&nstrchrs, addr, V8_OFF_STRING_LENGTH) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (slicelen != -1) - nstrchrs = slicelen; - - if ((flags & JSSTR_ISASCII) != 0) { - nstrbytes = nstrchrs; - nreadoffset = sliceoffset; - } else { - nstrbytes = 2 * nstrchrs; - nreadoffset = 2 * sliceoffset; - } - - nreadbytes = nstrbytes + sizeof ("\"\"") <= blen ? nstrbytes : - blen - sizeof ("\"\"[...]"); - - if (nreadbytes < 0) { - /* - * We don't even have the room to store the ellipsis; zero - * the buffer out and set the length to zero. - */ - *bufp = '\0'; - *lenp = 0; - return (0); - } - - if (verbose) - mdb_printf("length: %d chars (%d bytes), " - "will read %d bytes from offset %d\n", - nstrchrs, nstrbytes, nreadbytes, nreadoffset); - - if (nstrbytes == 0) { - (void) bsnprintf(bufp, lenp, "%s%s", - quoted ? "\"" : "", quoted ? "\"" : ""); - return (0); - } - - buf[0] = '\0'; - - if ((flags & JSSTR_ISASCII) != 0) { - if (mdb_readstr(buf, nreadbytes + 1, - addr + V8_OFF_SEQASCIISTR_CHARS + nreadoffset) == -1) { - v8_warn("failed to read SeqString data"); - return (-1); - } - - if (nreadbytes != nstrbytes) - (void) strlcat(buf, "[...]", blen); - - (void) bsnprintf(bufp, lenp, "%s%s%s", - quoted ? "\"" : "", buf, quoted ? "\"" : ""); - } else { - if (mdb_readstr(buf, nreadbytes, - addr + V8_OFF_SEQTWOBYTESTR_CHARS + nreadoffset) == -1) { - v8_warn("failed to read SeqTwoByteString data"); - return (-1); - } - - (void) bsnprintf(bufp, lenp, "%s", quoted ? "\"" : ""); - for (i = 0; i < nreadbytes; i += 2) { - /*LINTED*/ - chrval = *((uint16_t *)(buf + i)); - (void) bsnprintf(bufp, lenp, "%c", - (isascii(chrval) || chrval == 0) ? - (char)chrval : '?'); - } - if (nreadbytes != nstrbytes) - (void) bsnprintf(bufp, lenp, "[...]"); - (void) bsnprintf(bufp, lenp, "%s", quoted ? "\"" : ""); - } - - return (0); -} - -static int -jsstr_print_cons(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) -{ - boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; - boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; - uintptr_t ptr1, ptr2; - - if (read_heap_ptr(&ptr1, addr, V8_OFF_CONSSTRING_FIRST) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (read_heap_ptr(&ptr2, addr, V8_OFF_CONSSTRING_SECOND) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (verbose) { - mdb_printf("ptr1: %p\n", ptr1); - mdb_printf("ptr2: %p\n", ptr2); - } - - if (quoted) - (void) bsnprintf(bufp, lenp, "\""); - - flags = JSSTR_BUMPDEPTH(flags) & ~JSSTR_QUOTED; - - if (jsstr_print(ptr1, flags, bufp, lenp) != 0) - return (-1); - - if (jsstr_print(ptr2, flags, bufp, lenp) != 0) - return (-1); - - if (quoted) - (void) bsnprintf(bufp, lenp, "\""); - - return (0); -} - -static int -jsstr_print_sliced(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) -{ - uintptr_t parent, offset, length; - uint8_t typebyte; - boolean_t verbose = flags & JSSTR_VERBOSE ? B_TRUE : B_FALSE; - boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; - - if (read_heap_ptr(&parent, addr, V8_OFF_SLICEDSTRING_PARENT) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (read_heap_smi(&offset, addr, V8_OFF_SLICEDSTRING_OFFSET) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (read_heap_smi(&length, addr, V8_OFF_STRING_LENGTH) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (verbose) - mdb_printf("parent: %p, offset = %d, length = %d\n", - parent, offset, length); - - if (read_typebyte(&typebyte, parent) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (0); - } - - if (!V8_STRREP_SEQ(typebyte)) { - (void) bsnprintf(bufp, lenp, - ""); - return (0); - } - - if (quoted) - (void) bsnprintf(bufp, lenp, "\""); - - flags = JSSTR_BUMPDEPTH(flags) & ~JSSTR_QUOTED; - - if (V8_STRENC_ASCII(typebyte)) - flags |= JSSTR_ISASCII; - - if (jsstr_print_seq(parent, flags, bufp, lenp, offset, length) != 0) - return (-1); - - if (quoted) - (void) bsnprintf(bufp, lenp, "\""); - - return (0); -} - -static int -jsstr_print_external(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp) -{ - uintptr_t ptr1, ptr2; - size_t blen = *lenp + 1; - char *buf; - boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE; - int rval = -1; - - if ((flags & JSSTR_ISASCII) == 0) { - (void) bsnprintf(bufp, lenp, ""); - return (0); - } - - if (flags & JSSTR_VERBOSE) - mdb_printf("assuming Node.js string\n"); - - if (read_heap_ptr(&ptr1, addr, V8_OFF_EXTERNALSTRING_RESOURCE) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (mdb_vread(&ptr2, sizeof (ptr2), - ptr1 + NODE_OFF_EXTSTR_DATA) == -1) { - (void) bsnprintf(bufp, lenp, "", - ptr1 + NODE_OFF_EXTSTR_DATA); - return (-1); - } - - buf = mdb_alloc(blen, UM_SLEEP); - - if (mdb_readstr(buf, blen, ptr2) == -1) { - (void) bsnprintf(bufp, lenp, ""); - goto out; - } - - if (buf[0] != '\0' && !isascii(buf[0])) { - (void) bsnprintf(bufp, lenp, ""); - goto out; - } - - (void) bsnprintf(bufp, lenp, "%s%s%s", - quoted ? "\"" : "", buf, quoted ? "\"" : ""); - - rval = 0; -out: - mdb_free(buf, blen); - - return (rval); -} - -/* - * Returns true if the given address refers to the named oddball object (e.g. - * "undefined"). Returns false on failure (since we shouldn't fail on the - * actual "undefined" value). - */ -static boolean_t -jsobj_is_oddball(uintptr_t addr, char *oddball) -{ - uint8_t type; - uintptr_t strptr; - const char *typename; - char buf[16]; - char *bufp = buf; - size_t len = sizeof (buf); - - v8_silent++; - - if (read_typebyte(&type, addr) != 0) { - v8_silent--; - return (B_FALSE); - } - - v8_silent--; - typename = enum_lookup_str(v8_types, type, ""); - if (strcmp(typename, "Oddball") != 0) - return (B_FALSE); - - if (read_heap_ptr(&strptr, addr, V8_OFF_ODDBALL_TO_STRING) == -1) - return (B_FALSE); - - if (jsstr_print(strptr, JSSTR_NUDE, &bufp, &len) != 0) - return (B_FALSE); - - return (strcmp(buf, oddball) == 0); -} - -static boolean_t -jsobj_is_undefined(uintptr_t addr) -{ - return (jsobj_is_oddball(addr, "undefined")); -} - -static boolean_t -jsobj_is_hole(uintptr_t addr) -{ - return (jsobj_is_oddball(addr, "hole")); -} - -static int -jsobj_properties(uintptr_t addr, - int (*func)(const char *, uintptr_t, void *), void *arg) -{ - uintptr_t ptr, map, elements; - uintptr_t *props = NULL, *descs = NULL, *content = NULL, *trans, *elts; - size_t size, nprops, ndescs, ncontent, ntrans, len; - ssize_t ii, rndescs; - uint8_t type, ninprops; - int rval = -1; - size_t ps = sizeof (uintptr_t); - ssize_t off; - - /* - * Objects have either "fast" properties represented with a FixedArray - * or slow properties represented with a Dictionary. - */ - if (mdb_vread(&ptr, ps, addr + V8_OFF_JSOBJECT_PROPERTIES) == -1) - return (-1); - - if (read_typebyte(&type, ptr) != 0) - return (-1); - - if (type != V8_TYPE_FIXEDARRAY) { - /* - * If our properties aren't a fixed array, we'll emit a member - * that contains the type name, but with a NULL value. - */ - char buf[256]; - - (void) mdb_snprintf(buf, sizeof (buf), "<%s>", - enum_lookup_str(v8_types, type, "unknown")); - - return (func(buf, NULL, arg)); - } - - /* - * To iterate the properties, we need to examine the instance - * descriptors of the associated Map object. Depending on the version - * of V8, this might be found directly from the map -- or indirectly - * via the transitions array. - */ - if (mdb_vread(&map, ps, addr + V8_OFF_HEAPOBJECT_MAP) == -1) - goto err; - - /* - * Check to see if our elements member is an array and non-zero; if - * so, it contains numerically-named properties. - */ - if (V8_ELEMENTS_KIND_SHIFT != -1 && - read_heap_ptr(&elements, addr, V8_OFF_JSOBJECT_ELEMENTS) == 0 && - read_heap_array(elements, &elts, &len, UM_SLEEP) == 0 && len != 0) { - uint8_t bit_field2, kind; - size_t sz = len * sizeof (uintptr_t); - - if (mdb_vread(&bit_field2, sizeof (bit_field2), - map + V8_OFF_MAP_BIT_FIELD2) == -1) { - mdb_free(elts, sz); - goto err; - } - - kind = bit_field2 >> V8_ELEMENTS_KIND_SHIFT; - kind &= (1 << V8_ELEMENTS_KIND_BITCOUNT) - 1; - - if (kind == V8_ELEMENTS_FAST_ELEMENTS || - kind == V8_ELEMENTS_FAST_HOLEY_ELEMENTS) { - for (ii = 0; ii < len; ii++) { - char name[10]; - - if (kind == V8_ELEMENTS_FAST_HOLEY_ELEMENTS && - jsobj_is_hole(elts[ii])) - continue; - - snprintf(name, sizeof (name), "%d", ii); - - if (func(name, elts[ii], arg) != 0) { - mdb_free(elts, sz); - goto err; - } - } - } else if (kind == V8_ELEMENTS_DICTIONARY_ELEMENTS) { - if (read_heap_dict(elements, func, arg) != 0) { - mdb_free(elts, sz); - goto err; - } - } - - mdb_free(elts, sz); - } - - if (V8_DICT_SHIFT != -1) { - uintptr_t bit_field3; - - if (mdb_vread(&bit_field3, sizeof (bit_field3), - map + V8_OFF_MAP_BIT_FIELD3) == -1) - goto err; - - if (V8_SMI_VALUE(bit_field3) & (1 << V8_DICT_SHIFT)) - return (read_heap_dict(ptr, func, arg)); - } else if (V8_OFF_MAP_INSTANCE_DESCRIPTORS != -1) { - uintptr_t bit_field3; - - if (mdb_vread(&bit_field3, sizeof (bit_field3), - map + V8_OFF_MAP_INSTANCE_DESCRIPTORS) == -1) - goto err; - - if (V8_SMI_VALUE(bit_field3) == (1 << V8_ISSHARED_SHIFT)) { - /* - * On versions of V8 prior to that used in 0.10, - * the instance descriptors were overloaded to also - * be bit_field3 -- and there was no way from that - * field to infer a dictionary type. Because we - * can't determine if the map is actually the - * hash_table_map, we assume that if it's an object - * that has kIsShared set, that it is in fact a - * dictionary -- an assumption that is assuredly in - * error in some cases. - */ - return (read_heap_dict(ptr, func, arg)); - } - } - - if (read_heap_array(ptr, &props, &nprops, UM_SLEEP) != 0) - goto err; - - if ((off = V8_OFF_MAP_INSTANCE_DESCRIPTORS) == -1) { - if (V8_OFF_MAP_TRANSITIONS == -1 || - V8_TRANSITIONS_IDX_DESC == -1 || - V8_PROP_IDX_CONTENT != -1) { - mdb_warn("missing instance_descriptors, but did " - "not find expected transitions array metadata; " - "cannot read properties\n"); - goto err; - } - - off = V8_OFF_MAP_TRANSITIONS; - } - - if (mdb_vread(&ptr, ps, map + off) == -1) - goto err; - - if (V8_OFF_MAP_INSTANCE_DESCRIPTORS == -1) { - if (read_heap_array(ptr, &trans, &ntrans, UM_SLEEP) != 0) - goto err; - - ptr = trans[V8_TRANSITIONS_IDX_DESC]; - mdb_free(trans, ntrans * sizeof (uintptr_t)); - } - - if (read_heap_array(ptr, &descs, &ndescs, UM_SLEEP) != 0) - goto err; - - if (read_size(&size, addr) != 0) - size = 0; - - if (mdb_vread(&ninprops, 1, map + V8_OFF_MAP_INOBJECT_PROPERTIES) == -1) - goto err; - - if (V8_PROP_IDX_CONTENT != -1 && V8_PROP_IDX_CONTENT < ndescs && - read_heap_array(descs[V8_PROP_IDX_CONTENT], &content, - &ncontent, UM_SLEEP) != 0) - goto err; - - if (V8_PROP_IDX_CONTENT == -1) { - /* - * On node v0.8 and later, the content is not stored in an - * orthogonal FixedArray, but rather with the descriptors. - */ - content = descs; - ncontent = ndescs; - rndescs = ndescs > V8_PROP_IDX_FIRST ? - (ndescs - V8_PROP_IDX_FIRST) / V8_PROP_DESC_SIZE : 0; - } else { - rndescs = ndescs - V8_PROP_IDX_FIRST; - } - - for (ii = 0; ii < rndescs; ii++) { - uintptr_t keyidx, validx, detidx, baseidx; - char buf[1024]; - intptr_t val; - size_t len = sizeof (buf); - char *c = buf; - - if (V8_PROP_IDX_CONTENT != -1) { - /* - * In node versions prior to v0.8, this was hardcoded - * in the V8 implementation, so we hardcode it here - * as well. - */ - keyidx = ii + V8_PROP_IDX_FIRST; - validx = ii << 1; - detidx = (ii << 1) + 1; - } else { - baseidx = V8_PROP_IDX_FIRST + (ii * V8_PROP_DESC_SIZE); - keyidx = baseidx + V8_PROP_DESC_KEY; - validx = baseidx + V8_PROP_DESC_VALUE; - detidx = baseidx + V8_PROP_DESC_DETAILS; - } - - if (detidx >= ncontent) { - v8_warn("property descriptor %d: detidx (%d) " - "out of bounds for content array (length %d)\n", - ii, detidx, ncontent); - continue; - } - - if (!V8_DESC_ISFIELD(content[detidx])) - continue; - - if (keyidx >= ndescs) { - v8_warn("property descriptor %d: keyidx (%d) " - "out of bounds for descriptor array (length %d)\n", - ii, keyidx, ndescs); - continue; - } - - if (jsstr_print(descs[keyidx], JSSTR_NUDE, &c, &len) != 0) - continue; - - val = (intptr_t)content[validx]; - - if (!V8_IS_SMI(val)) { - v8_warn("object %p: property descriptor %d: value " - "index value is not an SMI: %p\n", addr, ii, val); - continue; - } - - val = V8_SMI_VALUE(val) - ninprops; - - if (val < 0) { - /* property is stored directly in the object */ - if (mdb_vread(&ptr, sizeof (ptr), addr + V8_OFF_HEAP( - size + val * sizeof (uintptr_t))) == -1) { - v8_warn("object %p: failed to read in-object " - "property at %p\n", addr, addr + - V8_OFF_HEAP(size + val * - sizeof (uintptr_t))); - continue; - } - } else { - /* property should be in "props" array */ - if (val >= nprops) { - /* - * This can happen when properties are deleted. - * If this value isn't obviously corrupt, we'll - * just silently ignore it. - */ - if (val < rndescs) - continue; - - v8_warn("object %p: property descriptor %d: " - "value index value (%d) out of bounds " - "(%d)\n", addr, ii, val, nprops); - goto err; - } - - ptr = props[val]; - } - - if (func(buf, ptr, arg) != 0) - goto err; - } - - rval = 0; -err: - if (props != NULL) - mdb_free(props, nprops * sizeof (uintptr_t)); - - if (descs != NULL) - mdb_free(descs, ndescs * sizeof (uintptr_t)); - - if (content != NULL && V8_PROP_IDX_CONTENT != -1) - mdb_free(content, ncontent * sizeof (uintptr_t)); - - return (rval); -} - -/* - * Given the line endings table in "lendsp", computes the line number for the - * given token position and print the result into "buf". If "lendsp" is - * undefined, prints the token position instead. - */ -static int -jsfunc_lineno(uintptr_t lendsp, uintptr_t tokpos, - char *buf, size_t buflen, int *lineno) -{ - uintptr_t size, bufsz, lower, upper, ii = 0; - uintptr_t *data; - - if (lineno != NULL) - *lineno = -1; - - if (jsobj_is_undefined(lendsp)) { - /* - * 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)); - - if (lineno != NULL) - *lineno = 0; - - return (0); - } - - if (read_heap_smi(&size, lendsp, V8_OFF_FIXEDARRAY_LENGTH) != 0) - return (-1); - - bufsz = size * sizeof (data[0]); - - if ((data = mdb_alloc(bufsz, UM_NOSLEEP)) == NULL) { - v8_warn("failed to alloc %d bytes for FixedArray data", bufsz); - return (-1); - } - - if (mdb_vread(data, bufsz, lendsp + V8_OFF_FIXEDARRAY_DATA) != bufsz) { - v8_warn("failed to read FixedArray data"); - mdb_free(data, bufsz); - return (-1); - } - - lower = 0; - upper = size - 1; - - if (tokpos > data[upper]) { - (void) strlcpy(buf, "position out of range", buflen); - mdb_free(data, bufsz); - - if (lineno != NULL) - *lineno = 0; - - return (0); - } - - if (tokpos <= data[0]) { - (void) strlcpy(buf, "line 1", buflen); - mdb_free(data, bufsz); - - if (lineno != NULL) - *lineno = 1; - - return (0); - } - - while (upper >= 1) { - ii = (lower + upper) >> 1; - if (tokpos > data[ii]) - lower = ii + 1; - else if (tokpos <= data[ii - 1]) - upper = ii - 1; - else - break; - } - - if (lineno != NULL) - *lineno = ii + 1; - - (void) mdb_snprintf(buf, buflen, "line %d", ii + 1); - mdb_free(data, bufsz); - return (0); -} - -/* - * Given a Script object, prints nlines on either side of lineno, with each - * line prefixed by prefix (if non-NULL). - */ -static void -jsfunc_lines(uintptr_t scriptp, - uintptr_t start, uintptr_t end, int nlines, char *prefix) -{ - uintptr_t src; - char *buf, *bufp; - size_t bufsz = 1024, len; - int i, line, slop = 10; - boolean_t newline = B_TRUE; - int startline = -1, endline = -1; - - if (read_heap_ptr(&src, scriptp, V8_OFF_SCRIPT_SOURCE) != 0) - return; - - for (;;) { - if ((buf = mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL) { - mdb_warn("failed to allocate source code " - "buffer of size %d", bufsz); - return; - } - - bufp = buf; - len = bufsz; - - if (jsstr_print(src, JSSTR_NUDE, &bufp, &len) != 0) { - mdb_free(buf, bufsz); - return; - } - - if (len > slop) - break; - - mdb_free(buf, bufsz); - bufsz <<= 1; - } - - if (end >= bufsz) - return; - - /* - * First, take a pass to determine where our lines actually start. - */ - for (i = 0, line = 1; buf[i] != '\0'; i++) { - if (buf[i] == '\n') - line++; - - if (i == start) - startline = line; - - if (i == end) { - endline = line; - break; - } - } - - if (startline == -1 || endline == -1) { - mdb_warn("for script %p, could not determine startline/endline" - " (start %ld, end %ld, nlines %d)", - scriptp, start, end, nlines); - mdb_free(buf, bufsz); - return; - } - - for (i = 0, line = 1; buf[i] != '\0'; i++) { - if (buf[i] == '\n') { - line++; - newline = B_TRUE; - } - - if (line < startline - nlines) - continue; - - if (line > endline + nlines) - break; - - mdb_printf("%c", buf[i]); - - if (newline) { - if (line >= startline && line <= endline) - mdb_printf("%"); - - if (prefix != NULL) - mdb_printf(prefix, line); - - if (line >= startline && line <= endline) - mdb_printf("%"); - - newline = B_FALSE; - } - } - - mdb_printf("\n"); - - if (line == endline) - mdb_printf("%"); - - mdb_free(buf, bufsz); -} - -/* - * Given a SharedFunctionInfo object, prints into bufp a name of the function - * suitable for printing. This function attempts to infer a name for anonymous - * functions. - */ -static int -jsfunc_name(uintptr_t funcinfop, char **bufp, size_t *lenp) -{ - uintptr_t ptrp; - char *bufs = *bufp; - - if (read_heap_ptr(&ptrp, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_NAME) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (jsstr_print(ptrp, JSSTR_NUDE, bufp, lenp) != 0) - return (-1); - - if (*bufp != bufs) - return (0); - - if (read_heap_ptr(&ptrp, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_INFERRED_NAME) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (0); - } - - (void) bsnprintf(bufp, lenp, " (as "); - bufs = *bufp; - - if (jsstr_print(ptrp, JSSTR_NUDE, bufp, lenp) != 0) - return (-1); - - if (*bufp == bufs) - (void) bsnprintf(bufp, lenp, ""); - - (void) bsnprintf(bufp, lenp, ")"); - - return (0); -} - -/* - * JavaScript-level object printing - */ -typedef struct jsobj_print { - char **jsop_bufp; - size_t *jsop_lenp; - int jsop_indent; - uint64_t jsop_depth; - boolean_t jsop_printaddr; - uintptr_t jsop_baseaddr; - int jsop_nprops; - const char *jsop_member; - boolean_t jsop_found; - boolean_t jsop_descended; -} jsobj_print_t; - -static int jsobj_print_number(uintptr_t, jsobj_print_t *); -static int jsobj_print_oddball(uintptr_t, jsobj_print_t *); -static int jsobj_print_jsobject(uintptr_t, jsobj_print_t *); -static int jsobj_print_jsarray(uintptr_t, jsobj_print_t *); -static int jsobj_print_jsfunction(uintptr_t, jsobj_print_t *); -static int jsobj_print_jsdate(uintptr_t, jsobj_print_t *); - -static int -jsobj_print(uintptr_t addr, jsobj_print_t *jsop) -{ - uint8_t type; - const char *klass; - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - - const struct { - char *name; - int (*func)(uintptr_t, jsobj_print_t *); - } table[] = { - { "HeapNumber", jsobj_print_number }, - { "Oddball", jsobj_print_oddball }, - { "JSObject", jsobj_print_jsobject }, - { "JSArray", jsobj_print_jsarray }, - { "JSFunction", jsobj_print_jsfunction }, - { "JSDate", jsobj_print_jsdate }, - { NULL } - }, *ent; - - if (jsop->jsop_baseaddr != NULL && jsop->jsop_member == NULL) - (void) bsnprintf(bufp, lenp, "%p: ", jsop->jsop_baseaddr); - - if (jsop->jsop_printaddr && jsop->jsop_member == NULL) - (void) bsnprintf(bufp, lenp, "%p: ", addr); - - if (V8_IS_SMI(addr)) { - (void) bsnprintf(bufp, lenp, "%d", V8_SMI_VALUE(addr)); - return (0); - } - - if (!V8_IS_HEAPOBJECT(addr)) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (read_typebyte(&type, addr) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (V8_TYPE_STRING(type)) { - if (jsstr_print(addr, JSSTR_QUOTED, bufp, lenp) == -1) - return (-1); - - return (0); - } - - klass = enum_lookup_str(v8_types, type, ""); - - for (ent = &table[0]; ent->name != NULL; ent++) { - if (strcmp(klass, ent->name) == 0) { - jsop->jsop_descended = B_TRUE; - return (ent->func(addr, jsop)); - } - } - - (void) bsnprintf(bufp, lenp, - "", klass); - return (-1); -} - -static int -jsobj_print_number(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - double numval; - - if (read_heap_double(&numval, addr, V8_OFF_HEAPNUMBER_VALUE) == -1) - return (-1); - - if (numval == (long long)numval) - (void) bsnprintf(bufp, lenp, "%lld", (long long)numval); - else - (void) bsnprintf(bufp, lenp, "%e", numval); - - return (0); -} - -static int -jsobj_print_oddball(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - uintptr_t strptr; - - if (read_heap_ptr(&strptr, addr, V8_OFF_ODDBALL_TO_STRING) != 0) - return (-1); - - return (jsstr_print(strptr, JSSTR_NUDE, bufp, lenp)); -} - -static int -jsobj_print_prop(const char *desc, uintptr_t val, void *arg) -{ - jsobj_print_t *jsop = arg, descend; - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - - (void) bsnprintf(bufp, lenp, "%s\n%*s%s: ", jsop->jsop_nprops == 0 ? - "{" : "", jsop->jsop_indent + 4, "", desc); - - descend = *jsop; - descend.jsop_depth--; - descend.jsop_indent += 4; - - (void) jsobj_print(val, &descend); - (void) bsnprintf(bufp, lenp, ","); - - jsop->jsop_nprops++; - - return (0); -} - -static int -jsobj_print_prop_member(const char *desc, uintptr_t val, void *arg) -{ - jsobj_print_t *jsop = arg, descend; - const char *member = jsop->jsop_member, *next = member; - int rv; - - for (; *next != '\0' && *next != '.' && *next != '['; next++) - continue; - - if (*member == '[') { - mdb_warn("cannot use array indexing on an object\n"); - return (-1); - } - - if (strncmp(member, desc, next - member) != 0) - return (0); - - if (desc[next - member] != '\0') - return (0); - - /* - * This property matches the desired member; descend. - */ - descend = *jsop; - - if (*next == '\0') { - descend.jsop_member = NULL; - descend.jsop_found = B_TRUE; - } else { - descend.jsop_member = *next == '.' ? next + 1 : next; - } - - rv = jsobj_print(val, &descend); - jsop->jsop_found = descend.jsop_found; - - return (rv); -} - -static int -jsobj_print_jsobject(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - - if (jsop->jsop_member != NULL) - return (jsobj_properties(addr, jsobj_print_prop_member, jsop)); - - if (jsop->jsop_depth == 0) { - (void) bsnprintf(bufp, lenp, "[...]"); - return (0); - } - - jsop->jsop_nprops = 0; - - if (jsobj_properties(addr, jsobj_print_prop, jsop) != 0) - return (-1); - - if (jsop->jsop_nprops > 0) { - (void) bsnprintf(bufp, lenp, "\n%*s", jsop->jsop_indent, ""); - } else if (jsop->jsop_nprops == 0) { - (void) bsnprintf(bufp, lenp, "{"); - } else { - (void) bsnprintf(bufp, lenp, "{ /* unknown property */ "); - } - - (void) bsnprintf(bufp, lenp, "}"); - - return (0); -} - -static int -jsobj_print_jsarray_member(uintptr_t addr, jsobj_print_t *jsop) -{ - uintptr_t *elts; - jsobj_print_t descend; - uintptr_t ptr; - const char *member = jsop->jsop_member, *end, *p; - size_t elt = 0, place = 1, len, rv; - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - - if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (read_heap_array(ptr, &elts, &len, UM_SLEEP | UM_GC) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (*member != '[') { - mdb_warn("expected bracketed array index; " - "found '%s'\n", member); - return (-1); - } - - if ((end = strchr(member, ']')) == NULL) { - mdb_warn("missing array index terminator\n"); - return (-1); - } - - /* - * We know where our array index ends; convert it to an integer - * by stepping through it from least significant digit to most. - */ - for (p = end - 1; p > member; p--) { - if (*p < '0' || *p > '9') { - mdb_warn("illegal array index at '%c'\n", *p); - return (-1); - } - - elt += (*p - '0') * place; - place *= 10; - } - - if (place == 1) { - mdb_warn("missing array index\n"); - return (-1); - } - - if (elt >= len) { - mdb_warn("array index %d exceeds size of %d\n", elt, len); - return (-1); - } - - descend = *jsop; - - switch (*(++end)) { - case '\0': - descend.jsop_member = NULL; - descend.jsop_found = B_TRUE; - break; - - case '.': - descend.jsop_member = end + 1; - break; - - case '[': - descend.jsop_member = end; - break; - - default: - mdb_warn("illegal character '%c' following " - "array index terminator\n", *end); - return (-1); - } - - rv = jsobj_print(elts[elt], &descend); - jsop->jsop_found = descend.jsop_found; - - return (rv); -} - -static int -jsobj_print_jsarray(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - int indent = jsop->jsop_indent; - jsobj_print_t descend; - uintptr_t ptr; - uintptr_t *elts; - size_t ii, len; - - if (jsop->jsop_member != NULL) - return (jsobj_print_jsarray_member(addr, jsop)); - - if (jsop->jsop_depth == 0) { - (void) bsnprintf(bufp, lenp, "[...]"); - return (0); - } - - if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0) { - (void) bsnprintf(bufp, lenp, - ""); - return (-1); - } - - if (read_heap_array(ptr, &elts, &len, UM_SLEEP | UM_GC) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (len == 0) { - (void) bsnprintf(bufp, lenp, "[]"); - return (0); - } - - descend = *jsop; - descend.jsop_depth--; - descend.jsop_indent += 4; - - if (len == 1) { - (void) bsnprintf(bufp, lenp, "[ "); - (void) jsobj_print(elts[0], &descend); - (void) bsnprintf(bufp, lenp, " ]"); - return (0); - } - - (void) bsnprintf(bufp, lenp, "[\n"); - - for (ii = 0; ii < len && *lenp > 0; ii++) { - (void) bsnprintf(bufp, lenp, "%*s", indent + 4, ""); - (void) jsobj_print(elts[ii], &descend); - (void) bsnprintf(bufp, lenp, ",\n"); - } - - (void) bsnprintf(bufp, lenp, "%*s", indent, ""); - (void) bsnprintf(bufp, lenp, "]"); - - return (0); -} - -static int -jsobj_print_jsfunction(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - uintptr_t shared; - - if (read_heap_ptr(&shared, addr, V8_OFF_JSFUNCTION_SHARED) != 0) - return (-1); - - (void) bsnprintf(bufp, lenp, "function "); - return (jsfunc_name(shared, bufp, lenp) != 0); -} - -static int -jsobj_print_jsdate(uintptr_t addr, jsobj_print_t *jsop) -{ - char **bufp = jsop->jsop_bufp; - size_t *lenp = jsop->jsop_lenp; - char buf[128]; - uintptr_t value; - uint8_t type; - double numval; - - if (V8_OFF_JSDATE_VALUE == -1) { - (void) bsnprintf(bufp, lenp, "", buf); - return (0); - } - - if (read_heap_ptr(&value, addr, V8_OFF_JSDATE_VALUE) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (read_typebyte(&type, value) != 0) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - if (strcmp(enum_lookup_str(v8_types, type, ""), "HeapNumber") != 0) - return (-1); - - if (read_heap_double(&numval, value, V8_OFF_HEAPNUMBER_VALUE) == -1) { - (void) bsnprintf(bufp, lenp, ""); - return (-1); - } - - mdb_snprintf(buf, sizeof (buf), "%Y", - (time_t)((long long)numval / MILLISEC)); - (void) bsnprintf(bufp, lenp, "%lld (%s)", (long long)numval, buf); - - return (0); -} - -/* - * dcmd implementations - */ - -/* ARGSUSED */ -static int -dcmd_v8classes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - v8_class_t *clp; - - for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) - mdb_printf("%s\n", clp->v8c_name); - - return (DCMD_OK); -} - -static int -do_v8code(uintptr_t addr, boolean_t opt_d) -{ - uintptr_t instrlen; - ssize_t instroff = V8_OFF_CODE_INSTRUCTION_START; - - if (read_heap_ptr(&instrlen, addr, V8_OFF_CODE_INSTRUCTION_SIZE) != 0) - return (DCMD_ERR); - - mdb_printf("code: %p\n", addr); - mdb_printf("instructions: [%p, %p)\n", addr + instroff, - addr + instroff + instrlen); - - if (!opt_d) - return (DCMD_OK); - - mdb_set_dot(addr + instroff); - - do { - (void) mdb_inc_indent(8); /* gets reset by mdb_eval() */ - - /* - * This is absolutely awful. We want to disassemble the above - * range of instructions. Because we don't know how many there - * are, we can't use "::dis". We resort to evaluating "./i", - * but then we need to advance "." by the size of the - * instruction just printed. The only way to do that is by - * printing out "+", but we don't want that to show up, so we - * redirect it to /dev/null. - */ - if (mdb_eval("/i") != 0 || - mdb_eval("+=p ! cat > /dev/null") != 0) { - (void) mdb_dec_indent(8); - v8_warn("failed to disassemble at %p", mdb_get_dot()); - return (DCMD_ERR); - } - } while (mdb_get_dot() < addr + instroff + instrlen); - - (void) mdb_dec_indent(8); - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8code(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - boolean_t opt_d = B_FALSE; - - if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, B_TRUE, &opt_d, - NULL) != argc) - return (DCMD_USAGE); - - return (do_v8code(addr, opt_d)); -} - -/* ARGSUSED */ -static int -dcmd_v8function(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - uint8_t type; - uintptr_t funcinfop, scriptp, lendsp, tokpos, namep, codep; - char *bufp; - size_t len; - boolean_t opt_d = B_FALSE; - char buf[512]; - - if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, B_TRUE, &opt_d, - NULL) != argc) - return (DCMD_USAGE); - - v8_warnings++; - - if (read_typebyte(&type, addr) != 0) - goto err; - - if (strcmp(enum_lookup_str(v8_types, type, ""), "JSFunction") != 0) { - v8_warn("%p is not an instance of JSFunction\n", addr); - goto err; - } - - if (read_heap_ptr(&funcinfop, addr, V8_OFF_JSFUNCTION_SHARED) != 0 || - read_heap_ptr(&tokpos, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION) != 0 || - read_heap_ptr(&scriptp, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0 || - read_heap_ptr(&namep, scriptp, V8_OFF_SCRIPT_NAME) != 0 || - read_heap_ptr(&lendsp, scriptp, V8_OFF_SCRIPT_LINE_ENDS) != 0) - goto err; - - bufp = buf; - len = sizeof (buf); - if (jsfunc_name(funcinfop, &bufp, &len) != 0) - goto err; - - mdb_printf("%p: JSFunction: %s\n", addr, buf); - - bufp = buf; - len = sizeof (buf); - mdb_printf("defined at "); - - if (jsstr_print(namep, JSSTR_NUDE, &bufp, &len) == 0) - mdb_printf("%s ", buf); - - if (jsfunc_lineno(lendsp, tokpos, buf, sizeof (buf), NULL) == 0) - mdb_printf("%s", buf); - - mdb_printf("\n"); - - if (read_heap_ptr(&codep, - funcinfop, V8_OFF_SHAREDFUNCTIONINFO_CODE) != 0) - goto err; - - v8_warnings--; - - return (do_v8code(codep, opt_d)); - -err: - v8_warnings--; - return (DCMD_ERR); -} - -/* ARGSUSED */ -static int -dcmd_v8frametypes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - enum_print(v8_frametypes); - return (DCMD_OK); -} - -static void -dcmd_v8print_help(void) -{ - mdb_printf( - "Prints out \".\" (a V8 heap object) as an instance of its C++\n" - "class. With no arguments, the appropriate class is detected\n" - "automatically. The 'class' argument overrides this to print an\n" - "object as an instance of the given class. The list of known\n" - "classes can be viewed with ::jsclasses."); -} - -/* ARGSUSED */ -static int -dcmd_v8print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - const char *rqclass; - v8_class_t *clp; - char *bufp; - size_t len; - uint8_t type; - char buf[256]; - - if (argc < 1) { - /* - * If no type was specified, determine it automatically. - */ - bufp = buf; - len = sizeof (buf); - if (obj_jstype(addr, &bufp, &len, &type) != 0) - return (DCMD_ERR); - - if (type == 0) { - /* For SMI or Failure, just print out the type. */ - mdb_printf("%s\n", buf); - return (DCMD_OK); - } - - if ((rqclass = enum_lookup_str(v8_types, type, NULL)) == NULL) { - v8_warn("object has unknown type\n"); - return (DCMD_ERR); - } - } else { - if (argv[0].a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - rqclass = argv[0].a_un.a_str; - } - - for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) { - if (strcmp(rqclass, clp->v8c_name) == 0) - break; - } - - if (clp == NULL) { - v8_warn("unknown class '%s'\n", rqclass); - return (DCMD_USAGE); - } - - return (obj_print_class(addr, clp)); -} - -/* ARGSUSED */ -static int -dcmd_v8type(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - char buf[64]; - char *bufp = buf; - size_t len = sizeof (buf); - - if (obj_jstype(addr, &bufp, &len, NULL) != 0) - return (DCMD_ERR); - - mdb_printf("0x%p: %s\n", addr, buf); - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8types(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - enum_print(v8_types); - return (DCMD_OK); -} - -static int -load_current_context(uintptr_t *fpp, uintptr_t *raddrp) -{ - mdb_reg_t regfp, regip; - -#ifdef __amd64 - if (mdb_getareg(1, "rbp", ®fp) != 0 || - mdb_getareg(1, "rip", ®ip) != 0) { -#else -#ifdef __i386 - if (mdb_getareg(1, "ebp", ®fp) != 0 || - mdb_getareg(1, "eip", ®ip) != 0) { -#else -#error Unrecognized microprocessor -#endif -#endif - v8_warn("failed to load current context"); - return (-1); - } - - if (fpp != NULL) - *fpp = (uintptr_t)regfp; - - if (raddrp != NULL) - *raddrp = (uintptr_t)regip; - - return (0); -} - -static int -do_jsframe_special(uintptr_t fptr, uintptr_t raddr, char *prop) -{ - uintptr_t ftype; - 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) { - if (prop != NULL) - return (0); - - 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. - */ - if (mdb_vread(&ftype, sizeof (ftype), fptr + V8_OFF_FP_CONTEXT) != -1 && - V8_IS_SMI(ftype) && - (ftypename = enum_lookup_str(v8_frametypes, V8_SMI_VALUE(ftype), - NULL)) != NULL && strstr(ftypename, "ArgumentsAdaptor") != NULL) { - if (prop != NULL) - return (0); - - mdb_printf("%p %a <%s>\n", fptr, raddr, ftypename); - return (0); - } - - /* - * Other special frame types are indicated by a marker. - */ - if (mdb_vread(&ftype, sizeof (ftype), fptr + V8_OFF_FP_MARKER) != -1 && - V8_IS_SMI(ftype)) { - if (prop != NULL) - return (0); - - ftypename = enum_lookup_str(v8_frametypes, V8_SMI_VALUE(ftype), - NULL); - - if (ftypename != NULL) - mdb_printf("%p %a <%s>\n", fptr, raddr, ftypename); - else - mdb_printf("%p %a\n", fptr, raddr); - - return (0); - } - - return (-1); -} - -static int -do_jsframe(uintptr_t fptr, uintptr_t raddr, boolean_t verbose, - char *func, char *prop, uintptr_t nlines) -{ - uintptr_t funcp, funcinfop, tokpos, endpos, scriptp, lendsp, ptrp; - uintptr_t ii, nargs; - const char *typename; - char *bufp; - size_t len; - uint8_t type; - char buf[256]; - int lineno; - - /* - * Check for non-JavaScript frames first. - */ - if (func == NULL && do_jsframe_special(fptr, raddr, prop) == 0) - return (DCMD_OK); - - /* - * At this point we assume we're looking at a JavaScript frame. As with - * native frames, fish the address out of the parent frame. - */ - if (mdb_vread(&funcp, sizeof (funcp), - fptr + V8_OFF_FP_FUNCTION) == -1) { - v8_warn("failed to read stack at %p", - fptr + V8_OFF_FP_FUNCTION); - return (DCMD_ERR); - } - - /* - * Check if this thing is really a JSFunction at all. For some frames, - * it's a Code object, presumably indicating some internal frame. - */ - if (read_typebyte(&type, funcp) != 0 || - (typename = enum_lookup_str(v8_types, type, NULL)) == NULL) { - if (func != NULL || prop != NULL) - return (DCMD_OK); - - mdb_printf("%p %a\n", fptr, raddr); - return (DCMD_OK); - } - - if (strcmp("Code", typename) == 0) { - if (func != NULL || prop != NULL) - return (DCMD_OK); - - mdb_printf("%p %a internal (Code: %p)\n", fptr, raddr, funcp); - return (DCMD_OK); - } - - if (strcmp("JSFunction", typename) != 0) { - if (func != NULL || prop != NULL) - return (DCMD_OK); - - mdb_printf("%p %a unknown (%s: %p)", fptr, raddr, typename, - funcp); - return (DCMD_OK); - } - - if (read_heap_ptr(&funcinfop, funcp, V8_OFF_JSFUNCTION_SHARED) != 0) - return (DCMD_ERR); - - bufp = buf; - len = sizeof (buf); - if (jsfunc_name(funcinfop, &bufp, &len) != 0) - return (DCMD_ERR); - - if (func != NULL && strcmp(buf, func) != 0) - return (DCMD_OK); - - if (prop == NULL) - mdb_printf("%p %a %s (%p)\n", fptr, raddr, buf, funcp); - - if (!verbose && prop == NULL) - return (DCMD_OK); - - /* - * Although the token position is technically an SMI, we're going to - * byte-compare it to other SMI values so we don't want decode it here. - */ - if (read_heap_ptr(&tokpos, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_FUNCTION_TOKEN_POSITION) != 0) - return (DCMD_ERR); - - if (read_heap_ptr(&scriptp, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_SCRIPT) != 0) - return (DCMD_ERR); - - if (read_heap_ptr(&ptrp, scriptp, V8_OFF_SCRIPT_NAME) != 0) - return (DCMD_ERR); - - bufp = buf; - len = sizeof (buf); - (void) jsstr_print(ptrp, JSSTR_NUDE, &bufp, &len); - - if (prop != NULL && strcmp(prop, "file") == 0) { - mdb_printf("%s\n", buf); - return (DCMD_OK); - } - - if (prop == NULL) { - (void) mdb_inc_indent(4); - mdb_printf("file: %s\n", buf); - } - - if (read_heap_ptr(&lendsp, scriptp, V8_OFF_SCRIPT_LINE_ENDS) != 0) - return (DCMD_ERR); - - if (read_heap_smi(&nargs, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_LENGTH) == 0) { - for (ii = 0; ii < nargs; ii++) { - uintptr_t argptr; - char arg[10]; - - if (mdb_vread(&argptr, sizeof (argptr), - fptr + V8_OFF_FP_ARGS + (nargs - ii - 1) * - sizeof (uintptr_t)) == -1) - continue; - - (void) snprintf(arg, sizeof (arg), "arg%d", ii + 1); - - if (prop != NULL) { - if (strcmp(arg, prop) != 0) - continue; - - mdb_printf("%p\n", argptr); - return (DCMD_OK); - } - - bufp = buf; - len = sizeof (buf); - (void) obj_jstype(argptr, &bufp, &len, NULL); - - mdb_printf("arg%d: %p (%s)\n", (ii + 1), argptr, buf); - } - } - - (void) jsfunc_lineno(lendsp, tokpos, buf, sizeof (buf), &lineno); - - if (prop != NULL) { - if (strcmp(prop, "posn") == 0) { - mdb_printf("%s\n", buf); - return (DCMD_OK); - } - - mdb_warn("unknown frame property '%s'\n", prop); - return (DCMD_ERR); - } - - mdb_printf("posn: %s", buf); - - if (nlines != 0 && read_heap_smi(&endpos, funcinfop, - V8_OFF_SHAREDFUNCTIONINFO_END_POSITION) == 0) { - jsfunc_lines(scriptp, - V8_SMI_VALUE(tokpos), endpos, nlines, "%5d "); - } - - mdb_printf("\n"); - (void) mdb_dec_indent(4); - - return (DCMD_OK); -} - -typedef struct findjsobjects_prop { - struct findjsobjects_prop *fjsp_next; - char fjsp_desc[1]; -} findjsobjects_prop_t; - -typedef struct findjsobjects_instance { - uintptr_t fjsi_addr; - struct findjsobjects_instance *fjsi_next; -} findjsobjects_instance_t; - -typedef struct findjsobjects_obj { - findjsobjects_prop_t *fjso_props; - findjsobjects_prop_t *fjso_last; - size_t fjso_nprops; - findjsobjects_instance_t fjso_instances; - int fjso_ninstances; - avl_node_t fjso_node; - struct findjsobjects_obj *fjso_next; - boolean_t fjso_malformed; - char fjso_constructor[80]; -} findjsobjects_obj_t; - -typedef struct findjsobjects_stats { - int fjss_heapobjs; - int fjss_cached; - int fjss_typereads; - int fjss_jsobjs; - int fjss_objects; - int fjss_arrays; - int fjss_uniques; -} findjsobjects_stats_t; - -typedef struct findjsobjects_reference { - uintptr_t fjsrf_addr; - char *fjsrf_desc; - size_t fjsrf_index; - struct findjsobjects_reference *fjsrf_next; -} findjsobjects_reference_t; - -typedef struct findjsobjects_referent { - avl_node_t fjsr_node; - uintptr_t fjsr_addr; - findjsobjects_reference_t *fjsr_head; - findjsobjects_reference_t *fjsr_tail; - struct findjsobjects_referent *fjsr_next; -} findjsobjects_referent_t; - -typedef struct findjsobjects_state { - uintptr_t fjs_addr; - uintptr_t fjs_size; - boolean_t fjs_verbose; - boolean_t fjs_brk; - boolean_t fjs_allobjs; - boolean_t fjs_initialized; - boolean_t fjs_marking; - boolean_t fjs_referred; - avl_tree_t fjs_tree; - avl_tree_t fjs_referents; - findjsobjects_referent_t *fjs_head; - findjsobjects_referent_t *fjs_tail; - findjsobjects_obj_t *fjs_current; - findjsobjects_obj_t *fjs_objects; - findjsobjects_stats_t fjs_stats; -} findjsobjects_state_t; - -findjsobjects_obj_t * -findjsobjects_alloc(uintptr_t addr) -{ - findjsobjects_obj_t *obj; - - obj = mdb_zalloc(sizeof (findjsobjects_obj_t), UM_SLEEP); - obj->fjso_instances.fjsi_addr = addr; - obj->fjso_ninstances = 1; - - return (obj); -} - -void -findjsobjects_free(findjsobjects_obj_t *obj) -{ - findjsobjects_prop_t *prop, *next; - - for (prop = obj->fjso_props; prop != NULL; prop = next) { - next = prop->fjsp_next; - mdb_free(prop, sizeof (findjsobjects_prop_t) + - strlen(prop->fjsp_desc)); - } - - mdb_free(obj, sizeof (findjsobjects_obj_t)); -} - -int -findjsobjects_cmp(findjsobjects_obj_t *lhs, findjsobjects_obj_t *rhs) -{ - findjsobjects_prop_t *lprop, *rprop; - int rv; - - lprop = lhs->fjso_props; - rprop = rhs->fjso_props; - - while (lprop != NULL && rprop != NULL) { - if ((rv = strcmp(lprop->fjsp_desc, rprop->fjsp_desc)) != 0) - return (rv > 0 ? 1 : -1); - - lprop = lprop->fjsp_next; - rprop = rprop->fjsp_next; - } - - if (lprop != NULL) - return (1); - - if (rprop != NULL) - return (-1); - - if (lhs->fjso_nprops > rhs->fjso_nprops) - return (1); - - if (lhs->fjso_nprops < rhs->fjso_nprops) - return (-1); - - rv = strcmp(lhs->fjso_constructor, rhs->fjso_constructor); - - return (rv < 0 ? -1 : rv > 0 ? 1 : 0); -} - -int -findjsobjects_cmp_referents(findjsobjects_referent_t *lhs, - findjsobjects_referent_t *rhs) -{ - if (lhs->fjsr_addr < rhs->fjsr_addr) - return (-1); - - if (lhs->fjsr_addr > rhs->fjsr_addr) - return (1); - - return (0); -} - -int -findjsobjects_cmp_ninstances(const void *l, const void *r) -{ - findjsobjects_obj_t *lhs = *((findjsobjects_obj_t **)l); - findjsobjects_obj_t *rhs = *((findjsobjects_obj_t **)r); - size_t lprod = lhs->fjso_ninstances * lhs->fjso_nprops; - size_t rprod = rhs->fjso_ninstances * rhs->fjso_nprops; - - if (lprod < rprod) - return (-1); - - if (lprod > rprod) - return (1); - - if (lhs->fjso_ninstances < rhs->fjso_ninstances) - return (-1); - - if (lhs->fjso_ninstances > rhs->fjso_ninstances) - return (1); - - if (lhs->fjso_nprops < rhs->fjso_nprops) - return (-1); - - if (lhs->fjso_nprops > rhs->fjso_nprops) - return (1); - - return (0); -} - -/*ARGSUSED*/ -int -findjsobjects_prop(const char *desc, uintptr_t val, void *arg) -{ - findjsobjects_state_t *fjs = arg; - findjsobjects_obj_t *current = fjs->fjs_current; - findjsobjects_prop_t *prop; - - if (desc == NULL) - desc = ""; - - prop = mdb_zalloc(sizeof (findjsobjects_prop_t) + - strlen(desc), UM_SLEEP); - - strcpy(prop->fjsp_desc, desc); - - if (current->fjso_last != NULL) { - current->fjso_last->fjsp_next = prop; - } else { - current->fjso_props = prop; - } - - current->fjso_last = prop; - current->fjso_nprops++; - current->fjso_malformed = - val == NULL && current->fjso_nprops == 1 && desc[0] == '<'; - - return (0); -} - -static void -findjsobjects_constructor(findjsobjects_obj_t *obj) -{ - char *bufp = obj->fjso_constructor; - size_t len = sizeof (obj->fjso_constructor); - uintptr_t map, funcinfop; - uintptr_t addr = obj->fjso_instances.fjsi_addr; - uint8_t type; - - v8_silent++; - - if (read_heap_ptr(&map, addr, V8_OFF_HEAPOBJECT_MAP) != 0 || - read_heap_ptr(&addr, map, V8_OFF_MAP_CONSTRUCTOR) != 0) - goto out; - - if (read_typebyte(&type, addr) != 0) - goto out; - - if (strcmp(enum_lookup_str(v8_types, type, ""), "JSFunction") != 0) - goto out; - - if (read_heap_ptr(&funcinfop, addr, V8_OFF_JSFUNCTION_SHARED) != 0) - goto out; - - if (jsfunc_name(funcinfop, &bufp, &len) != 0) - goto out; -out: - v8_silent--; -} - -int -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 = V8_TYPE_JSOBJECT, jsarray = V8_TYPE_JSARRAY; - caddr_t range = mdb_alloc(size, UM_SLEEP); - uintptr_t base = addr, mapaddr; - - if (mdb_vread(range, size, addr) == -1) - return (0); - - for (limit = addr + size; addr < limit; addr++) { - findjsobjects_instance_t *inst; - findjsobjects_obj_t *obj; - avl_index_t where; - - if (V8_IS_SMI(addr)) - continue; - - if (!V8_IS_HEAPOBJECT(addr)) - continue; - - stats->fjss_heapobjs++; - - mapaddr = *((uintptr_t *)((uintptr_t)range + - (addr - base) + V8_OFF_HEAPOBJECT_MAP)); - - if (!V8_IS_HEAPOBJECT(mapaddr)) - continue; - - mapaddr += V8_OFF_MAP_INSTANCE_ATTRIBUTES; - stats->fjss_typereads++; - - if (mapaddr >= base && mapaddr < base + size) { - stats->fjss_cached++; - - type = *((uint8_t *)((uintptr_t)range + - (mapaddr - base))); - } else { - if (mdb_vread(&type, sizeof (uint8_t), mapaddr) == -1) - continue; - } - - if (type != jsobject && type != jsarray) - continue; - - stats->fjss_jsobjs++; - - fjs->fjs_current = findjsobjects_alloc(addr); - - if (type == jsobject) { - if (jsobj_properties(addr, - findjsobjects_prop, fjs) != 0) { - findjsobjects_free(fjs->fjs_current); - fjs->fjs_current = NULL; - continue; - } - - findjsobjects_constructor(fjs->fjs_current); - stats->fjss_objects++; - } else { - uintptr_t ptr; - size_t *nprops = &fjs->fjs_current->fjso_nprops; - ssize_t len = V8_OFF_JSARRAY_LENGTH; - ssize_t elems = V8_OFF_JSOBJECT_ELEMENTS; - ssize_t flen = V8_OFF_FIXEDARRAY_LENGTH; - uintptr_t nelems; - uint8_t t; - - if (read_heap_smi(nprops, addr, len) != 0 || - read_heap_ptr(&ptr, addr, elems) != 0 || - !V8_IS_HEAPOBJECT(ptr) || - read_typebyte(&t, ptr) != 0 || - t != V8_TYPE_FIXEDARRAY || - read_heap_smi(&nelems, ptr, flen) != 0 || - nelems < *nprops) { - findjsobjects_free(fjs->fjs_current); - fjs->fjs_current = NULL; - continue; - } - - strcpy(fjs->fjs_current->fjso_constructor, "Array"); - stats->fjss_arrays++; - } - - /* - * Now determine if we already have an object matching our - * properties. If we don't, we'll add our new object; if we - * do we'll merely enqueue our instance. - */ - obj = avl_find(&fjs->fjs_tree, fjs->fjs_current, &where); - - if (obj == NULL) { - avl_add(&fjs->fjs_tree, fjs->fjs_current); - fjs->fjs_current->fjso_next = fjs->fjs_objects; - fjs->fjs_objects = fjs->fjs_current; - fjs->fjs_current = NULL; - stats->fjss_uniques++; - continue; - } - - findjsobjects_free(fjs->fjs_current); - fjs->fjs_current = NULL; - - inst = mdb_alloc(sizeof (findjsobjects_instance_t), UM_SLEEP); - inst->fjsi_addr = addr; - inst->fjsi_next = obj->fjso_instances.fjsi_next; - obj->fjso_instances.fjsi_next = inst; - obj->fjso_ninstances++; - } - - mdb_free(range, size); - - return (0); -} - -static int -findjsobjects_mapping(findjsobjects_state_t *fjs, const prmap_t *pmp, - const char *name) -{ - if (name != NULL && !(fjs->fjs_brk && (pmp->pr_mflags & MA_BREAK))) - return (0); - - if (fjs->fjs_addr != NULL && (fjs->fjs_addr < pmp->pr_vaddr || - fjs->fjs_addr >= pmp->pr_vaddr + pmp->pr_size)) - return (0); - - return (findjsobjects_range(fjs, pmp->pr_vaddr, pmp->pr_size)); -} - -static void -findjsobjects_references_add(findjsobjects_state_t *fjs, uintptr_t val, - const char *desc, size_t index) -{ - findjsobjects_referent_t search, *referent; - findjsobjects_reference_t *reference; - - search.fjsr_addr = val; - - if ((referent = avl_find(&fjs->fjs_referents, &search, NULL)) == NULL) - return; - - reference = mdb_zalloc(sizeof (*reference), UM_SLEEP | UM_GC); - reference->fjsrf_addr = fjs->fjs_addr; - - if (desc != NULL) { - reference->fjsrf_desc = - mdb_alloc(strlen(desc) + 1, UM_SLEEP | UM_GC); - (void) strcpy(reference->fjsrf_desc, desc); - } else { - reference->fjsrf_index = index; - } - - if (referent->fjsr_head == NULL) { - referent->fjsr_head = reference; - } else { - referent->fjsr_tail->fjsrf_next = reference; - } - - referent->fjsr_tail = reference; -} - -static int -findjsobjects_references_prop(const char *desc, uintptr_t val, void *arg) -{ - findjsobjects_references_add(arg, val, desc, -1); - - return (0); -} - -static void -findjsobjects_references_array(findjsobjects_state_t *fjs, - findjsobjects_obj_t *obj) -{ - findjsobjects_instance_t *inst = &obj->fjso_instances; - uintptr_t *elts; - size_t i, len; - - for (; inst != NULL; inst = inst->fjsi_next) { - uintptr_t addr = inst->fjsi_addr, ptr; - - if (read_heap_ptr(&ptr, addr, V8_OFF_JSOBJECT_ELEMENTS) != 0 || - read_heap_array(ptr, &elts, &len, UM_SLEEP) != 0) - continue; - - fjs->fjs_addr = addr; - - for (i = 0; i < len; i++) - findjsobjects_references_add(fjs, elts[i], NULL, i); - - mdb_free(elts, len * sizeof (uintptr_t)); - } -} - -static void -findjsobjects_referent(findjsobjects_state_t *fjs, uintptr_t addr) -{ - findjsobjects_referent_t search, *referent; - - search.fjsr_addr = addr; - - if (avl_find(&fjs->fjs_referents, &search, NULL) != NULL) { - assert(fjs->fjs_marking); - mdb_warn("%p is already marked; ignoring\n", addr); - return; - } - - referent = mdb_zalloc(sizeof (findjsobjects_referent_t), UM_SLEEP); - referent->fjsr_addr = addr; - - avl_add(&fjs->fjs_referents, referent); - - if (fjs->fjs_tail != NULL) { - fjs->fjs_tail->fjsr_next = referent; - } else { - fjs->fjs_head = referent; - } - - fjs->fjs_tail = referent; - - if (fjs->fjs_marking) - mdb_printf("findjsobjects: marked %p\n", addr); -} - -static void -findjsobjects_references(findjsobjects_state_t *fjs) -{ - findjsobjects_reference_t *reference; - findjsobjects_referent_t *referent; - avl_tree_t *referents = &fjs->fjs_referents; - findjsobjects_obj_t *obj; - void *cookie = NULL; - uintptr_t addr; - - fjs->fjs_referred = B_FALSE; - - v8_silent++; - - /* - * First traverse over all objects and arrays, looking for references - * to our designated referent(s). - */ - for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { - findjsobjects_instance_t *head = &obj->fjso_instances, *inst; - - if (obj->fjso_nprops != 0 && obj->fjso_props == NULL) { - findjsobjects_references_array(fjs, obj); - continue; - } - - for (inst = head; inst != NULL; inst = inst->fjsi_next) { - fjs->fjs_addr = inst->fjsi_addr; - - (void) jsobj_properties(inst->fjsi_addr, - findjsobjects_references_prop, fjs); - } - } - - v8_silent--; - fjs->fjs_addr = NULL; - - /* - * Now go over our referent(s), reporting any references that we have - * accumulated. - */ - for (referent = fjs->fjs_head; referent != NULL; - referent = referent->fjsr_next) { - addr = referent->fjsr_addr; - - if ((reference = referent->fjsr_head) == NULL) { - mdb_printf("%p is not referred to by a " - "known object.\n", addr); - continue; - } - - for (; reference != NULL; reference = reference->fjsrf_next) { - mdb_printf("%p referred to by %p", - addr, reference->fjsrf_addr); - - if (reference->fjsrf_desc == NULL) { - mdb_printf("[%d]\n", reference->fjsrf_index); - } else { - mdb_printf(".%s\n", reference->fjsrf_desc); - } - } - } - - /* - * Finally, destroy our referent nodes. - */ - while ((referent = avl_destroy_nodes(referents, &cookie)) != NULL) - mdb_free(referent, sizeof (findjsobjects_referent_t)); - - fjs->fjs_head = NULL; - fjs->fjs_tail = NULL; -} - -static findjsobjects_instance_t * -findjsobjects_instance(findjsobjects_state_t *fjs, uintptr_t addr, - findjsobjects_instance_t **headp) -{ - findjsobjects_obj_t *obj; - - for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { - findjsobjects_instance_t *head = &obj->fjso_instances, *inst; - - for (inst = head; inst != NULL; inst = inst->fjsi_next) { - if (inst->fjsi_addr == addr) { - *headp = head; - return (inst); - } - } - } - - return (NULL); -} - -/*ARGSUSED*/ -static void -findjsobjects_match_all(findjsobjects_obj_t *obj, const char *ignored) -{ - mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); -} - -static void -findjsobjects_match_propname(findjsobjects_obj_t *obj, const char *propname) -{ - findjsobjects_prop_t *prop; - - for (prop = obj->fjso_props; prop != NULL; prop = prop->fjsp_next) { - if (strcmp(prop->fjsp_desc, propname) == 0) { - mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); - return; - } - } -} - -static void -findjsobjects_match_constructor(findjsobjects_obj_t *obj, - const char *constructor) -{ - if (strcmp(constructor, obj->fjso_constructor) == 0) - mdb_printf("%p\n", obj->fjso_instances.fjsi_addr); -} - -static int -findjsobjects_match(findjsobjects_state_t *fjs, uintptr_t addr, - uint_t flags, void (*func)(findjsobjects_obj_t *, const char *), - const char *match) -{ - findjsobjects_obj_t *obj; - - if (!(flags & DCMD_ADDRSPEC)) { - for (obj = fjs->fjs_objects; obj != NULL; - obj = obj->fjso_next) { - if (obj->fjso_malformed && !fjs->fjs_allobjs) - continue; - - func(obj, match); - } - - return (DCMD_OK); - } - - /* - * First, look for the specified address among the representative - * objects. - */ - for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { - if (obj->fjso_instances.fjsi_addr == addr) { - func(obj, match); - return (DCMD_OK); - } - } - - /* - * We didn't find it among the representative objects; iterate over - * all objects. - */ - for (obj = fjs->fjs_objects; obj != NULL; obj = obj->fjso_next) { - findjsobjects_instance_t *head = &obj->fjso_instances, *inst; - - for (inst = head; inst != NULL; inst = inst->fjsi_next) { - if (inst->fjsi_addr == addr) { - func(obj, match); - return (DCMD_OK); - } - } - } - - mdb_warn("%p does not correspond to a known object\n", addr); - return (DCMD_ERR); -} - -static void -findjsobjects_print(findjsobjects_obj_t *obj) -{ - int col = 19 + (sizeof (uintptr_t) * 2) + strlen("..."), len; - uintptr_t addr = obj->fjso_instances.fjsi_addr; - findjsobjects_prop_t *prop; - - mdb_printf("%?p %8d %8d ", - addr, obj->fjso_ninstances, obj->fjso_nprops); - - if (obj->fjso_constructor[0] != '\0') { - mdb_printf("%s%s", obj->fjso_constructor, - obj->fjso_props != NULL ? ": " : ""); - col += strlen(obj->fjso_constructor) + 2; - } - - for (prop = obj->fjso_props; prop != NULL; prop = prop->fjsp_next) { - if (col + (len = strlen(prop->fjsp_desc) + 2) < 80) { - mdb_printf("%s%s", prop->fjsp_desc, - prop->fjsp_next != NULL ? ", " : ""); - col += len; - } else { - mdb_printf("..."); - break; - } - } - - mdb_printf("\n", col); -} - -static void -dcmd_findjsobjects_help(void) -{ - mdb_printf("%s\n\n", -"Finds all JavaScript objects in the V8 heap via brute force iteration over\n" -"all mapped anonymous memory. (This can take up to several minutes on large\n" -"dumps.) The output consists of representative objects, the number of\n" -"instances of that object and the number of properties on the object --\n" -"followed by the constructor and first few properties of the objects. Once\n" -"run, subsequent calls to ::findjsobjects use cached data. If provided an\n" -"address (and in the absence of -r, described below), ::findjsobjects treats\n" -"the address as that of a representative object, and lists all instances of\n" -"that object (that is, all objects that have a matching property signature)."); - - mdb_dec_indent(2); - mdb_printf("%OPTIONS%\n"); - mdb_inc_indent(2); - - mdb_printf("%s\n", -" -b Include the heap denoted by the brk(2) (normally excluded)\n" -" -c cons Display representative objects with the specified constructor\n" -" -p prop Display representative objects that have the specified property\n" -" -l List all objects that match the representative object\n" -" -m Mark specified object for later reference determination via -r\n" -" -r Find references to the specified and/or marked object(s)\n" -" -v Provide verbose statistics\n"); -} - -static int -dcmd_findjsobjects(uintptr_t addr, - uint_t flags, int argc, const mdb_arg_t *argv) -{ - static findjsobjects_state_t fjs; - static findjsobjects_stats_t *stats = &fjs.fjs_stats; - findjsobjects_obj_t *obj; - struct ps_prochandle *Pr; - boolean_t references = B_FALSE, listlike = B_FALSE; - const char *propname = NULL; - const char *constructor = NULL; - - fjs.fjs_verbose = B_FALSE; - fjs.fjs_brk = B_FALSE; - fjs.fjs_marking = B_FALSE; - fjs.fjs_allobjs = B_FALSE; - - if (mdb_getopts(argc, argv, - 'a', MDB_OPT_SETBITS, B_TRUE, &fjs.fjs_allobjs, - 'b', MDB_OPT_SETBITS, B_TRUE, &fjs.fjs_brk, - 'c', MDB_OPT_STR, &constructor, - 'l', MDB_OPT_SETBITS, B_TRUE, &listlike, - 'm', MDB_OPT_SETBITS, B_TRUE, &fjs.fjs_marking, - 'p', MDB_OPT_STR, &propname, - 'r', MDB_OPT_SETBITS, B_TRUE, &references, - 'v', MDB_OPT_SETBITS, B_TRUE, &fjs.fjs_verbose, - NULL) != argc) - return (DCMD_USAGE); - - if (!fjs.fjs_initialized) { - avl_create(&fjs.fjs_tree, - (int(*)(const void *, const void *))findjsobjects_cmp, - sizeof (findjsobjects_obj_t), - offsetof(findjsobjects_obj_t, fjso_node)); - - avl_create(&fjs.fjs_referents, - (int(*)(const void *, const void *)) - findjsobjects_cmp_referents, - sizeof (findjsobjects_referent_t), - offsetof(findjsobjects_referent_t, fjsr_node)); - - fjs.fjs_initialized = B_TRUE; - } - - if (avl_is_empty(&fjs.fjs_tree)) { - findjsobjects_obj_t **sorted; - int nobjs, i; - hrtime_t start = gethrtime(); - - if (mdb_get_xdata("pshandle", &Pr, sizeof (Pr)) == -1) { - mdb_warn("couldn't read pshandle xdata"); - return (DCMD_ERR); - } - - v8_silent++; - - if (Pmapping_iter(Pr, - (proc_map_f *)findjsobjects_mapping, &fjs) != 0) { - v8_silent--; - return (DCMD_ERR); - } - - if ((nobjs = avl_numnodes(&fjs.fjs_tree)) != 0) { - /* - * We have the objects -- now sort them. - */ - sorted = mdb_alloc(nobjs * sizeof (void *), - UM_SLEEP | UM_GC); - - for (obj = fjs.fjs_objects, i = 0; obj != NULL; - obj = obj->fjso_next, i++) { - sorted[i] = obj; - } - - qsort(sorted, avl_numnodes(&fjs.fjs_tree), - sizeof (void *), findjsobjects_cmp_ninstances); - - for (i = 1, fjs.fjs_objects = sorted[0]; i < nobjs; i++) - sorted[i - 1]->fjso_next = sorted[i]; - - sorted[nobjs - 1]->fjso_next = NULL; - } - - v8_silent--; - - if (fjs.fjs_verbose) { - const char *f = "findjsobjects: %30s => %d\n"; - int elapsed = (int)((gethrtime() - start) / NANOSEC); - - mdb_printf(f, "elapsed time (seconds)", elapsed); - mdb_printf(f, "heap objects", stats->fjss_heapobjs); - mdb_printf(f, "type reads", stats->fjss_typereads); - mdb_printf(f, "cached reads", stats->fjss_cached); - mdb_printf(f, "JavaScript objects", stats->fjss_jsobjs); - mdb_printf(f, "processed objects", stats->fjss_objects); - mdb_printf(f, "processed arrays", stats->fjss_arrays); - mdb_printf(f, "unique objects", stats->fjss_uniques); - } - } - - if (listlike && !(flags & DCMD_ADDRSPEC)) { - if (propname != NULL || constructor != NULL) { - char opt = propname != NULL ? 'p' : 'c'; - - mdb_warn("cannot specify -l with -%c; instead, pipe " - "output of ::findjsobjects -%c to " - "::findjsobjects -l\n", opt, opt); - return (DCMD_ERR); - } - - return (findjsobjects_match(&fjs, addr, flags, - findjsobjects_match_all, NULL)); - } - - if (propname != NULL) { - if (constructor != NULL) { - mdb_warn("cannot specify both a property name " - "and a constructor\n"); - return (DCMD_ERR); - } - - return (findjsobjects_match(&fjs, addr, flags, - findjsobjects_match_propname, propname)); - } - - if (constructor != NULL) { - return (findjsobjects_match(&fjs, addr, flags, - findjsobjects_match_constructor, constructor)); - } - - if (references && !(flags & DCMD_ADDRSPEC) && - avl_is_empty(&fjs.fjs_referents)) { - mdb_warn("must specify or mark an object to find references\n"); - return (DCMD_ERR); - } - - if (fjs.fjs_marking && !(flags & DCMD_ADDRSPEC)) { - mdb_warn("must specify an object to mark\n"); - return (DCMD_ERR); - } - - if (references && fjs.fjs_marking) { - mdb_warn("can't both mark an object and find its references\n"); - return (DCMD_ERR); - } - - if (flags & DCMD_ADDRSPEC) { - findjsobjects_instance_t *inst, *head; - - /* - * If we've been passed an address, it's to either list like - * objects (-l), mark an object (-m) or find references to the - * specified/marked objects (-r). (Note that the absence of - * any of these options implies -l.) - */ - inst = findjsobjects_instance(&fjs, addr, &head); - - if (inst == NULL) { - mdb_warn("%p is not a valid object\n", addr); - return (DCMD_ERR); - } - - if (!references && !fjs.fjs_marking) { - for (inst = head; inst != NULL; inst = inst->fjsi_next) - mdb_printf("%p\n", inst->fjsi_addr); - - return (DCMD_OK); - } - - if (!listlike) { - findjsobjects_referent(&fjs, inst->fjsi_addr); - } else { - for (inst = head; inst != NULL; inst = inst->fjsi_next) - findjsobjects_referent(&fjs, inst->fjsi_addr); - } - } - - if (references) - findjsobjects_references(&fjs); - - if (references || fjs.fjs_marking) - return (DCMD_OK); - - mdb_printf("%?s %8s %8s %s\n", "OBJECT", - "#OBJECTS", "#PROPS", "CONSTRUCTOR: PROPS"); - - for (obj = fjs.fjs_objects; obj != NULL; obj = obj->fjso_next) { - if (obj->fjso_malformed && !fjs.fjs_allobjs) - continue; - - findjsobjects_print(obj); - } - - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_jsframe(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - uintptr_t fptr, raddr; - boolean_t opt_v = B_FALSE, opt_i = B_FALSE; - char *opt_f = NULL, *opt_p = NULL; - uintptr_t opt_n = 5; - - if (mdb_getopts(argc, argv, - 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, - 'i', MDB_OPT_SETBITS, B_TRUE, &opt_i, - 'f', MDB_OPT_STR, &opt_f, - 'n', MDB_OPT_UINTPTR, &opt_n, - 'p', MDB_OPT_STR, &opt_p, NULL) != argc) - return (DCMD_USAGE); - - /* - * As with $C, we assume we are given a *pointer* to the frame pointer - * for a frame, rather than the actual frame pointer for the frame of - * interest. This is needed to show the instruction pointer, which is - * actually stored with the next frame. For debugging, this can be - * overridden with the "-i" option (for "immediate"). - */ - if (opt_i) - return (do_jsframe(addr, 0, opt_v, opt_f, opt_p, opt_n)); - - if (mdb_vread(&raddr, sizeof (raddr), - addr + sizeof (uintptr_t)) == -1) { - mdb_warn("failed to read return address from %p", - addr + sizeof (uintptr_t)); - return (DCMD_ERR); - } - - if (mdb_vread(&fptr, sizeof (fptr), addr) == -1) { - mdb_warn("failed to read frame pointer from %p", addr); - return (DCMD_ERR); - } - - if (fptr == NULL) - return (DCMD_OK); - - return (do_jsframe(fptr, raddr, opt_v, opt_f, opt_p, opt_n)); -} - -/* ARGSUSED */ -static int -dcmd_jsprint(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - char *buf, *bufp; - size_t bufsz = 262144, len = bufsz; - jsobj_print_t jsop; - boolean_t opt_b = B_FALSE; - int rv, i; - - bzero(&jsop, sizeof (jsop)); - jsop.jsop_depth = 2; - jsop.jsop_printaddr = B_FALSE; - - i = mdb_getopts(argc, argv, - 'a', MDB_OPT_SETBITS, B_TRUE, &jsop.jsop_printaddr, - 'b', MDB_OPT_SETBITS, B_TRUE, &opt_b, - 'd', MDB_OPT_UINT64, &jsop.jsop_depth, NULL); - - if (opt_b) - jsop.jsop_baseaddr = addr; - - do { - if (i != argc) { - const mdb_arg_t *member = &argv[i++]; - - if (member->a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - jsop.jsop_member = member->a_un.a_str; - } - - for (;;) { - if ((buf = bufp = - mdb_zalloc(bufsz, UM_NOSLEEP)) == NULL) - return (DCMD_ERR); - - jsop.jsop_bufp = &bufp; - jsop.jsop_lenp = &len; - - rv = jsobj_print(addr, &jsop); - - if (len > 0) - break; - - mdb_free(buf, bufsz); - bufsz <<= 1; - len = bufsz; - } - - if (jsop.jsop_member == NULL && rv != 0) { - if (!jsop.jsop_descended) - mdb_warn("%s\n", buf); - - return (DCMD_ERR); - } - - 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); - jsop.jsop_found = B_FALSE; - jsop.jsop_baseaddr = NULL; - } while (i < argc); - - mdb_printf("\n"); - - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8field(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - v8_class_t *clp; - v8_field_t *flp; - const char *klass, *field; - uintptr_t offset = 0; - - /* - * We may be invoked with either two arguments (class and field name) or - * three (an offset to save). - */ - if (argc != 2 && argc != 3) - return (DCMD_USAGE); - - if (argv[0].a_type != MDB_TYPE_STRING || - argv[1].a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - klass = argv[0].a_un.a_str; - field = argv[1].a_un.a_str; - - if (argc == 3) { - if (argv[2].a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - offset = mdb_strtoull(argv[2].a_un.a_str); - } - - for (clp = v8_classes; clp != NULL; clp = clp->v8c_next) - if (strcmp(clp->v8c_name, klass) == 0) - break; - - if (clp == NULL) { - (void) mdb_printf("error: no such class: \"%s\"", klass); - return (DCMD_ERR); - } - - for (flp = clp->v8c_fields; flp != NULL; flp = flp->v8f_next) - if (strcmp(field, flp->v8f_name) == 0) - break; - - if (flp == NULL) { - if (argc == 2) { - mdb_printf("error: no such field in class \"%s\": " - "\"%s\"", klass, field); - return (DCMD_ERR); - } - - flp = conf_field_create(clp, field, offset); - if (flp == NULL) { - mdb_warn("failed to create field"); - return (DCMD_ERR); - } - } else if (argc == 3) { - flp->v8f_offset = offset; - } - - mdb_printf("%s::%s at offset 0x%x\n", klass, field, flp->v8f_offset); - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8array(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - uint8_t type; - uintptr_t *array; - size_t ii, len; - - if (read_typebyte(&type, addr) != 0) - return (DCMD_ERR); - - if (type != V8_TYPE_FIXEDARRAY) { - mdb_warn("%p is not an instance of FixedArray\n", addr); - return (DCMD_ERR); - } - - if (read_heap_array(addr, &array, &len, UM_SLEEP | UM_GC) != 0) - return (DCMD_ERR); - - for (ii = 0; ii < len; ii++) - mdb_printf("%p\n", array[ii]); - - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_jsstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - uintptr_t raddr, opt_n = 5; - boolean_t opt_v = B_FALSE; - char *opt_f = NULL, *opt_p = NULL; - - if (mdb_getopts(argc, argv, - 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, - 'f', MDB_OPT_STR, &opt_f, - 'n', MDB_OPT_UINTPTR, &opt_n, - 'p', MDB_OPT_STR, &opt_p, - NULL) != argc) - return (DCMD_USAGE); - - /* - * The "::jsframe" walker iterates the valid frame pointers, but the - * "::jsframe" dcmd looks at the frame after the one it was given, so we - * have to explicitly examine the top frame here. - */ - if (!(flags & DCMD_ADDRSPEC)) { - if (load_current_context(&addr, &raddr) != 0 || - do_jsframe(addr, raddr, opt_v, opt_f, opt_p, opt_n) != 0) - return (DCMD_ERR); - } - - if (mdb_pwalk_dcmd("jsframe", "jsframe", argc, argv, addr) == -1) - return (DCMD_ERR); - - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8str(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - boolean_t opt_v = B_FALSE; - char buf[512 * 1024]; - char *bufp; - size_t len; - - if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, B_TRUE, &opt_v, - NULL) != argc) - return (DCMD_USAGE); - - bufp = buf; - len = sizeof (buf); - if (jsstr_print(addr, (opt_v ? JSSTR_VERBOSE : JSSTR_NONE) | - JSSTR_QUOTED, &bufp, &len) != 0) - return (DCMD_ERR); - - mdb_printf("%s\n", buf); - return (DCMD_OK); -} - -static void -dcmd_v8load_help(void) -{ - v8_cfg_t *cfp, **cfgpp; - - mdb_printf( - "To traverse in-memory V8 structures, the V8 dmod requires\n" - "configuration that describes the layout of various V8 structures\n" - "in memory. Normally, this information is pulled from metadata\n" - "in the target binary. However, it's possible to use the module\n" - "with a binary not built with metadata by loading one of the\n" - "canned configurations.\n\n"); - - mdb_printf("Available configurations:\n"); - - (void) mdb_inc_indent(4); - - for (cfgpp = v8_cfgs; *cfgpp != NULL; cfgpp++) { - cfp = *cfgpp; - mdb_printf("%-10s %s\n", cfp->v8cfg_name, cfp->v8cfg_label); - } - - (void) mdb_dec_indent(4); -} - -/* ARGSUSED */ -static int -dcmd_v8load(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - v8_cfg_t *cfgp = NULL, **cfgpp; - - if (v8_classes != NULL) { - mdb_warn("v8 module already configured\n"); - return (DCMD_ERR); - } - - if (argc < 1 || argv->a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - for (cfgpp = v8_cfgs; *cfgpp != NULL; cfgpp++) { - cfgp = *cfgpp; - if (strcmp(argv->a_un.a_str, cfgp->v8cfg_name) == 0) - break; - } - - if (cfgp == NULL || cfgp->v8cfg_name == NULL) { - mdb_warn("unknown configuration: \"%s\"\n", argv->a_un.a_str); - return (DCMD_ERR); - } - - if (autoconfigure(cfgp) == -1) { - mdb_warn("autoconfigure failed\n"); - return (DCMD_ERR); - } - - mdb_printf("V8 dmod configured based on %s\n", cfgp->v8cfg_name); - return (DCMD_OK); -} - -/* ARGSUSED */ -static int -dcmd_v8warnings(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - v8_warnings ^= 1; - mdb_printf("v8 warnings are now %s\n", v8_warnings ? "on" : "off"); - - return (DCMD_OK); -} - -static int -walk_jsframes_init(mdb_walk_state_t *wsp) -{ - if (wsp->walk_addr != NULL) - return (WALK_NEXT); - - if (load_current_context(&wsp->walk_addr, NULL) != 0) - return (WALK_ERR); - - return (WALK_NEXT); -} - -static int -walk_jsframes_step(mdb_walk_state_t *wsp) -{ - uintptr_t addr, next; - int rv; - - addr = wsp->walk_addr; - rv = wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata); - - if (rv != WALK_NEXT) - return (rv); - - if (mdb_vread(&next, sizeof (next), addr) == -1) - return (WALK_ERR); - - if (next == NULL) - return (WALK_DONE); - - wsp->walk_addr = next; - 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_SLEEP | 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_SLEEP | 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 - */ - -static const mdb_dcmd_t v8_mdb_dcmds[] = { - /* - * Commands to inspect JavaScript-level state - */ - { "jsframe", ":[-iv] [-f function] [-p property] [-n numlines]", - "summarize a JavaScript stack frame", dcmd_jsframe }, - { "jsprint", ":[-ab] [-d depth] [member]", "print a JavaScript object", - dcmd_jsprint }, - { "jsstack", "[-v] [-f function] [-p property] [-n numlines]", - "print a JavaScript stacktrace", dcmd_jsstack }, - { "findjsobjects", "?[-vb] [-r | -c cons | -p prop]", "find JavaScript " - "objects", dcmd_findjsobjects, dcmd_findjsobjects_help }, - - /* - * Commands to inspect V8-level state - */ - { "v8array", ":", "print elements of a V8 FixedArray", - dcmd_v8array }, - { "v8classes", NULL, "list known V8 heap object C++ classes", - dcmd_v8classes }, - { "v8code", ":[-d]", "print information about a V8 Code object", - dcmd_v8code }, - { "v8field", "classname fieldname offset", - "manually add a field to a given class", dcmd_v8field }, - { "v8function", ":[-d]", "print JSFunction object details", - dcmd_v8function }, - { "v8load", "version", "load canned config for a specific V8 version", - dcmd_v8load, dcmd_v8load_help }, - { "v8frametypes", NULL, "list known V8 frame types", - dcmd_v8frametypes }, - { "v8print", ":[class]", "print a V8 heap object", - dcmd_v8print, dcmd_v8print_help }, - { "v8str", ":[-v]", "print the contents of a V8 string", - dcmd_v8str }, - { "v8type", ":", "print the type of a V8 heap object", - dcmd_v8type }, - { "v8types", NULL, "list known V8 heap object types", - dcmd_v8types }, - { "v8warnings", NULL, "toggle V8 warnings", - dcmd_v8warnings }, - - { NULL } -}; - -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 } -}; - -static mdb_modinfo_t v8_mdb = { MDB_API_VERSION, v8_mdb_dcmds, v8_mdb_walkers }; - -static void -configure(void) -{ - char *success; - v8_cfg_t *cfgp = NULL; - GElf_Sym sym; - - if (mdb_readsym(&v8_major, sizeof (v8_major), - "_ZN2v88internal7Version6major_E") == -1 || - mdb_readsym(&v8_minor, sizeof (v8_minor), - "_ZN2v88internal7Version6minor_E") == -1 || - mdb_readsym(&v8_build, sizeof (v8_build), - "_ZN2v88internal7Version6build_E") == -1 || - mdb_readsym(&v8_patch, sizeof (v8_patch), - "_ZN2v88internal7Version6patch_E") == -1) { - mdb_warn("failed to determine V8 version"); - return; - } - - mdb_printf("V8 version: %d.%d.%d.%d\n", - v8_major, v8_minor, v8_build, v8_patch); - - /* - * First look for debug metadata embedded within the binary, which may - * be present in recent V8 versions built with postmortem metadata. - */ - if (mdb_lookup_by_name("v8dbg_SmiTag", &sym) == 0) { - cfgp = &v8_cfg_target; - success = "Autoconfigured V8 support from target"; - } else if (v8_major == 3 && v8_minor == 1 && v8_build == 8) { - cfgp = &v8_cfg_04; - success = "Configured V8 support based on node v0.4"; - } else if (v8_major == 3 && v8_minor == 6 && v8_build == 6) { - cfgp = &v8_cfg_06; - success = "Configured V8 support based on node v0.6"; - } else { - mdb_printf("mdb_v8: target has no debug metadata and " - "no existing config found\n"); - return; - } - - if (autoconfigure(cfgp) != 0) { - mdb_warn("failed to autoconfigure from target; " - "commands may have incorrect results!\n"); - return; - } - - mdb_printf("%s\n", success); -} - -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); -} diff --git a/deps/mdb_v8/mdb_v8.gyp b/deps/mdb_v8/mdb_v8.gyp deleted file mode 100644 index e7bb659925..0000000000 --- a/deps/mdb_v8/mdb_v8.gyp +++ /dev/null @@ -1,22 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'mdb_v8', - 'product_prefix': '', - 'type': 'loadable_module', - 'cflags': [ '-fPIC' ], - 'sources': [ - 'mdb_v8.c', - 'mdb_v8_cfg.c', - 'v8cfg.h', - 'v8dbg.h', - ], - 'link_settings': { - 'libraries': [ - '-lproc', - '-lavl', - ], - }, - }, - ], -} diff --git a/deps/mdb_v8/mdb_v8_cfg.c b/deps/mdb_v8/mdb_v8_cfg.c deleted file mode 100644 index 219b84f4fd..0000000000 --- a/deps/mdb_v8/mdb_v8_cfg.c +++ /dev/null @@ -1,725 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * mdb_v8_cfg.c: canned configurations for previous V8 versions. - * - * The functions and data defined here enable this dmod to support debugging - * Node.js binaries that predated V8's built-in postmortem debugging support. - */ - -#include "v8cfg.h" - -/*ARGSUSED*/ -static int -v8cfg_target_iter(v8_cfg_t *cfgp, int (*func)(mdb_symbol_t *, void *), - void *arg) -{ - return (mdb_symbol_iter(MDB_OBJ_EVERY, MDB_DYNSYM, - MDB_BIND_GLOBAL | MDB_TYPE_OBJECT | MDB_TYPE_FUNC, - func, arg)); -} - -/*ARGSUSED*/ -static int -v8cfg_target_readsym(v8_cfg_t *cfgp, const char *name, intptr_t *valp) -{ - int val, rval; - - if ((rval = mdb_readsym(&val, sizeof (val), name)) != -1) - *valp = (intptr_t)val; - - return (rval); -} - -/* - * Analog of mdb_symbol_iter() for a canned configuration. - */ -static int -v8cfg_canned_iter(v8_cfg_t *cfgp, int (*func)(mdb_symbol_t *, void *), - void *arg) -{ - v8_cfg_symbol_t *v8sym; - mdb_symbol_t mdbsym; - int rv; - - for (v8sym = cfgp->v8cfg_symbols; v8sym->v8cs_name != NULL; v8sym++) { - mdbsym.sym_name = v8sym->v8cs_name; - mdbsym.sym_object = NULL; - mdbsym.sym_sym = NULL; - mdbsym.sym_table = 0; - mdbsym.sym_id = 0; - - if ((rv = func(&mdbsym, arg)) != 0) - return (rv); - } - - return (0); -} - -/* - * Analog of mdb_readsym() for a canned configuration. - */ -static int -v8cfg_canned_readsym(v8_cfg_t *cfgp, const char *name, intptr_t *valp) -{ - v8_cfg_symbol_t *v8sym; - - for (v8sym = cfgp->v8cfg_symbols; v8sym->v8cs_name != NULL; v8sym++) { - if (strcmp(name, v8sym->v8cs_name) == 0) - break; - } - - if (v8sym->v8cs_name == NULL) - return (-1); - - *valp = v8sym->v8cs_value; - return (0); -} - -/* - * Canned configuration for the V8 bundled with Node.js v0.4.8 and later. - */ -static v8_cfg_symbol_t v8_symbols_node_04[] = { - { "v8dbg_type_AccessCheckInfo__ACCESS_CHECK_INFO_TYPE", 0x91 }, - { "v8dbg_type_AccessorInfo__ACCESSOR_INFO_TYPE", 0x90 }, - { "v8dbg_type_BreakPointInfo__BREAK_POINT_INFO_TYPE", 0x9b }, - { "v8dbg_type_ByteArray__BYTE_ARRAY_TYPE", 0x86 }, - { "v8dbg_type_CallHandlerInfo__CALL_HANDLER_INFO_TYPE", 0x93 }, - { "v8dbg_type_Code__CODE_TYPE", 0x81 }, - { "v8dbg_type_CodeCache__CODE_CACHE_TYPE", 0x99 }, - { "v8dbg_type_ConsString__CONS_ASCII_STRING_TYPE", 0x5 }, - { "v8dbg_type_ConsString__CONS_ASCII_SYMBOL_TYPE", 0x45 }, - { "v8dbg_type_ConsString__CONS_STRING_TYPE", 0x1 }, - { "v8dbg_type_ConsString__CONS_SYMBOL_TYPE", 0x41 }, - { "v8dbg_type_DebugInfo__DEBUG_INFO_TYPE", 0x9a }, - { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_STRING_TYPE", 0x6 }, - { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_SYMBOL_TYPE", 0x46 }, - { "v8dbg_type_ExternalByteArray__EXTERNAL_BYTE_ARRAY_TYPE", 0x88 }, - { "v8dbg_type_ExternalFloatArray__EXTERNAL_FLOAT_ARRAY_TYPE", 0x8e }, - { "v8dbg_type_ExternalIntArray__EXTERNAL_INT_ARRAY_TYPE", 0x8c }, - { "v8dbg_type_ExternalShortArray__EXTERNAL_SHORT_ARRAY_TYPE", 0x8a }, - { "v8dbg_type_ExternalString__EXTERNAL_STRING_TYPE", 0x2 }, - { "v8dbg_type_ExternalString__EXTERNAL_SYMBOL_TYPE", 0x42 }, - { "v8dbg_type_ExternalUnsignedByteArray__" - "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE", 0x89 }, - { "v8dbg_type_ExternalUnsignedIntArray__" - "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE", 0x8d }, - { "v8dbg_type_ExternalUnsignedShortArray__" - "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE", 0x8b }, - { "v8dbg_type_FixedArray__FIXED_ARRAY_TYPE", 0x9c }, - { "v8dbg_type_FunctionTemplateInfo__" - "FUNCTION_TEMPLATE_INFO_TYPE", 0x94 }, - { "v8dbg_type_HeapNumber__HEAP_NUMBER_TYPE", 0x84 }, - { "v8dbg_type_InterceptorInfo__INTERCEPTOR_INFO_TYPE", 0x92 }, - { "v8dbg_type_JSArray__JS_ARRAY_TYPE", 0xa5 }, - { "v8dbg_type_JSBuiltinsObject__JS_BUILTINS_OBJECT_TYPE", 0xa3 }, - { "v8dbg_type_JSFunction__JS_FUNCTION_TYPE", 0xa7 }, - { "v8dbg_type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE", 0xa2 }, - { "v8dbg_type_JSGlobalPropertyCell__" - "JS_GLOBAL_PROPERTY_CELL_TYPE", 0x83 }, - { "v8dbg_type_JSGlobalProxy__JS_GLOBAL_PROXY_TYPE", 0xa4 }, - { "v8dbg_type_JSMessageObject__JS_MESSAGE_OBJECT_TYPE", 0x9e }, - { "v8dbg_type_JSObject__JS_OBJECT_TYPE", 0xa0 }, - { "v8dbg_type_JSRegExp__JS_REGEXP_TYPE", 0xa6 }, - { "v8dbg_type_JSValue__JS_VALUE_TYPE", 0x9f }, - { "v8dbg_type_Map__MAP_TYPE", 0x80 }, - { "v8dbg_type_ObjectTemplateInfo__OBJECT_TEMPLATE_INFO_TYPE", 0x95 }, - { "v8dbg_type_Oddball__ODDBALL_TYPE", 0x82 }, - { "v8dbg_type_Script__SCRIPT_TYPE", 0x98 }, - { "v8dbg_type_SeqAsciiString__ASCII_STRING_TYPE", 0x4 }, - { "v8dbg_type_SeqAsciiString__ASCII_SYMBOL_TYPE", 0x44 }, - { "v8dbg_type_SharedFunctionInfo__SHARED_FUNCTION_INFO_TYPE", 0x9d }, - { "v8dbg_type_SignatureInfo__SIGNATURE_INFO_TYPE", 0x96 }, - { "v8dbg_type_String__STRING_TYPE", 0x0 }, - { "v8dbg_type_String__SYMBOL_TYPE", 0x40 }, - { "v8dbg_type_TypeSwitchInfo__TYPE_SWITCH_INFO_TYPE", 0x97 }, - - { "v8dbg_class_AccessCheckInfo__data__Object", 0xc }, - { "v8dbg_class_AccessCheckInfo__indexed_callback__Object", 0x8 }, - { "v8dbg_class_AccessCheckInfo__named_callback__Object", 0x4 }, - { "v8dbg_class_AccessorInfo__data__Object", 0xc }, - { "v8dbg_class_AccessorInfo__flag__Smi", 0x14 }, - { "v8dbg_class_AccessorInfo__getter__Object", 0x4 }, - { "v8dbg_class_AccessorInfo__name__Object", 0x10 }, - { "v8dbg_class_AccessorInfo__setter__Object", 0x8 }, - { "v8dbg_class_BreakPointInfo__break_point_objects__Object", 0x10 }, - { "v8dbg_class_BreakPointInfo__code_position__Smi", 0x4 }, - { "v8dbg_class_BreakPointInfo__source_position__Smi", 0x8 }, - { "v8dbg_class_BreakPointInfo__statement_position__Smi", 0xc }, - { "v8dbg_class_ByteArray__length__SMI", 0x4 }, - { "v8dbg_class_CallHandlerInfo__callback__Object", 0x4 }, - { "v8dbg_class_CallHandlerInfo__data__Object", 0x8 }, - { "v8dbg_class_Code__deoptimization_data__FixedArray", 0xc }, - { "v8dbg_class_Code__instruction_size__int", 0x4 }, - { "v8dbg_class_Code__instruction_start__int", 0x20 }, - { "v8dbg_class_Code__relocation_info__ByteArray", 0x8 }, - { "v8dbg_class_CodeCache__default_cache__FixedArray", 0x4 }, - { "v8dbg_class_CodeCache__normal_type_cache__Object", 0x8 }, - { "v8dbg_class_ConsString__first__String", 0xc }, - { "v8dbg_class_ConsString__second__String", 0x10 }, - { "v8dbg_class_DebugInfo__break_points__FixedArray", 0x14 }, - { "v8dbg_class_DebugInfo__code__Code", 0xc }, - { "v8dbg_class_DebugInfo__original_code__Code", 0x8 }, - { "v8dbg_class_DebugInfo__shared__SharedFunctionInfo", 0x4 }, - { "v8dbg_class_ExternalString__resource__Object", 0xc }, - { "v8dbg_class_FixedArray__data__uintptr_t", 0x8 }, - { "v8dbg_class_FixedArray__length__SMI", 0x4 }, - { "v8dbg_class_FunctionTemplateInfo__access_check_info__Object", 0x38 }, - { "v8dbg_class_FunctionTemplateInfo__call_code__Object", 0x10 }, - { "v8dbg_class_FunctionTemplateInfo__class_name__Object", 0x2c }, - { "v8dbg_class_FunctionTemplateInfo__flag__Smi", 0x3c }, - { "v8dbg_class_FunctionTemplateInfo__" - "indexed_property_handler__Object", 0x24 }, - { "v8dbg_class_FunctionTemplateInfo__" - "instance_call_handler__Object", 0x34 }, - { "v8dbg_class_FunctionTemplateInfo__instance_template__Object", 0x28 }, - { "v8dbg_class_FunctionTemplateInfo__" - "named_property_handler__Object", 0x20 }, - { "v8dbg_class_FunctionTemplateInfo__parent_template__Object", 0x1c }, - { "v8dbg_class_FunctionTemplateInfo__" - "property_accessors__Object", 0x14 }, - { "v8dbg_class_FunctionTemplateInfo__" - "prototype_template__Object", 0x18 }, - { "v8dbg_class_FunctionTemplateInfo__serial_number__Object", 0xc }, - { "v8dbg_class_FunctionTemplateInfo__signature__Object", 0x30 }, - { "v8dbg_class_GlobalObject__builtins__JSBuiltinsObject", 0xc }, - { "v8dbg_class_GlobalObject__global_context__Context", 0x10 }, - { "v8dbg_class_GlobalObject__global_receiver__JSObject", 0x14 }, - { "v8dbg_class_HeapNumber__value__SMI", 0x4 }, - { "v8dbg_class_HeapObject__map__Map", 0x0 }, - { "v8dbg_class_InterceptorInfo__data__Object", 0x18 }, - { "v8dbg_class_InterceptorInfo__deleter__Object", 0x10 }, - { "v8dbg_class_InterceptorInfo__enumerator__Object", 0x14 }, - { "v8dbg_class_InterceptorInfo__getter__Object", 0x4 }, - { "v8dbg_class_InterceptorInfo__query__Object", 0xc }, - { "v8dbg_class_InterceptorInfo__setter__Object", 0x8 }, - { "v8dbg_class_JSArray__length__Object", 0xc }, - { "v8dbg_class_JSFunction__literals__FixedArray", 0x1c }, - { "v8dbg_class_JSFunction__next_function_link__Object", 0x20 }, - { "v8dbg_class_JSFunction__prototype_or_initial_map__Object", 0x10 }, - { "v8dbg_class_JSFunction__shared__SharedFunctionInfo", 0x14 }, - { "v8dbg_class_JSGlobalProxy__context__Object", 0xc }, - { "v8dbg_class_JSMessageObject__arguments__JSArray", 0x10 }, - { "v8dbg_class_JSMessageObject__end_position__SMI", 0x24 }, - { "v8dbg_class_JSMessageObject__script__Object", 0x14 }, - { "v8dbg_class_JSMessageObject__stack_frames__Object", 0x1c }, - { "v8dbg_class_JSMessageObject__stack_trace__Object", 0x18 }, - { "v8dbg_class_JSMessageObject__start_position__SMI", 0x20 }, - { "v8dbg_class_JSMessageObject__type__String", 0xc }, - { "v8dbg_class_JSObject__elements__Object", 0x8 }, - { "v8dbg_class_JSObject__properties__FixedArray", 0x4 }, - { "v8dbg_class_JSRegExp__data__Object", 0xc }, - { "v8dbg_class_JSValue__value__Object", 0xc }, - { "v8dbg_class_Map__code_cache__Object", 0x18 }, - { "v8dbg_class_Map__constructor__Object", 0x10 }, - { "v8dbg_class_Map__inobject_properties__int", 0x5 }, - { "v8dbg_class_Map__instance_size__int", 0x4 }, - { "v8dbg_class_Map__instance_attributes__int", 0x8 }, - { "v8dbg_class_Map__instance_descriptors__DescriptorArray", 0x14 }, - { "v8dbg_class_ObjectTemplateInfo__constructor__Object", 0xc }, - { "v8dbg_class_ObjectTemplateInfo__" - "internal_field_count__Object", 0x10 }, - { "v8dbg_class_Oddball__to_number__Object", 0x8 }, - { "v8dbg_class_Oddball__to_string__String", 0x4 }, - { "v8dbg_class_Script__column_offset__Smi", 0x10 }, - { "v8dbg_class_Script__compilation_type__Smi", 0x24 }, - { "v8dbg_class_Script__context_data__Object", 0x18 }, - { "v8dbg_class_Script__data__Object", 0x14 }, - { "v8dbg_class_Script__eval_from_instructions_offset__Smi", 0x34 }, - { "v8dbg_class_Script__eval_from_shared__Object", 0x30 }, - { "v8dbg_class_Script__id__Object", 0x2c }, - { "v8dbg_class_Script__line_ends__Object", 0x28 }, - { "v8dbg_class_Script__line_offset__Smi", 0xc }, - { "v8dbg_class_Script__name__Object", 0x8 }, - { "v8dbg_class_Script__source__Object", 0x4 }, - { "v8dbg_class_Script__type__Smi", 0x20 }, - { "v8dbg_class_Script__wrapper__Proxy", 0x1c }, - { "v8dbg_class_SeqAsciiString__chars__char", 0xc }, - { "v8dbg_class_SharedFunctionInfo__code__Code", 0x8 }, - { "v8dbg_class_SharedFunctionInfo__compiler_hints__SMI", 0x50 }, - { "v8dbg_class_SharedFunctionInfo__construct_stub__Code", 0x10 }, - { "v8dbg_class_SharedFunctionInfo__debug_info__Object", 0x20 }, - { "v8dbg_class_SharedFunctionInfo__end_position__SMI", 0x48 }, - { "v8dbg_class_SharedFunctionInfo__" - "expected_nof_properties__SMI", 0x3c }, - { "v8dbg_class_SharedFunctionInfo__formal_parameter_count__SMI", 0x38 }, - { "v8dbg_class_SharedFunctionInfo__function_data__Object", 0x18 }, - { "v8dbg_class_SharedFunctionInfo__" - "function_token_position__SMI", 0x4c }, - { "v8dbg_class_SharedFunctionInfo__inferred_name__String", 0x24 }, - { "v8dbg_class_SharedFunctionInfo__initial_map__Object", 0x28 }, - { "v8dbg_class_SharedFunctionInfo__instance_class_name__Object", 0x14 }, - { "v8dbg_class_SharedFunctionInfo__length__SMI", 0x34 }, - { "v8dbg_class_SharedFunctionInfo__name__Object", 0x4 }, - { "v8dbg_class_SharedFunctionInfo__num_literals__SMI", 0x40 }, - { "v8dbg_class_SharedFunctionInfo__opt_count__SMI", 0x58 }, - { "v8dbg_class_SharedFunctionInfo__script__Object", 0x1c }, - { "v8dbg_class_SharedFunctionInfo__" - "start_position_and_type__SMI", 0x44 }, - { "v8dbg_class_SharedFunctionInfo__" - "this_property_assignments__Object", 0x2c }, - { "v8dbg_class_SharedFunctionInfo__" - "this_property_assignments_count__SMI", 0x54 }, - { "v8dbg_class_SignatureInfo__args__Object", 0x8 }, - { "v8dbg_class_SignatureInfo__receiver__Object", 0x4 }, - { "v8dbg_class_String__length__SMI", 0x4 }, - { "v8dbg_class_TemplateInfo__property_list__Object", 0x8 }, - { "v8dbg_class_TemplateInfo__tag__Object", 0x4 }, - { "v8dbg_class_TypeSwitchInfo__types__Object", 0x4 }, - - { "v8dbg_parent_AccessCheckInfo__Struct", 0x0 }, - { "v8dbg_parent_AccessorInfo__Struct", 0x0 }, - { "v8dbg_parent_BreakPointInfo__Struct", 0x0 }, - { "v8dbg_parent_ByteArray__HeapObject", 0x0 }, - { "v8dbg_parent_CallHandlerInfo__Struct", 0x0 }, - { "v8dbg_parent_Code__HeapObject", 0x0 }, - { "v8dbg_parent_CodeCache__Struct", 0x0 }, - { "v8dbg_parent_ConsString__String", 0x0 }, - { "v8dbg_parent_DebugInfo__Struct", 0x0 }, - { "v8dbg_parent_DeoptimizationInputData__FixedArray", 0x0 }, - { "v8dbg_parent_DeoptimizationOutputData__FixedArray", 0x0 }, - { "v8dbg_parent_DescriptorArray__FixedArray", 0x0 }, - { "v8dbg_parent_ExternalArray__HeapObject", 0x0 }, - { "v8dbg_parent_ExternalAsciiString__ExternalString", 0x0 }, - { "v8dbg_parent_ExternalByteArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalFloatArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalIntArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalShortArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalString__String", 0x0 }, - { "v8dbg_parent_ExternalTwoByteString__ExternalString", 0x0 }, - { "v8dbg_parent_ExternalUnsignedByteArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalUnsignedIntArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalUnsignedShortArray__ExternalArray", 0x0 }, - { "v8dbg_parent_Failure__MaybeObject", 0x0 }, - { "v8dbg_parent_FixedArray__HeapObject", 0x0 }, - { "v8dbg_parent_FunctionTemplateInfo__TemplateInfo", 0x0 }, - { "v8dbg_parent_GlobalObject__JSObject", 0x0 }, - { "v8dbg_parent_HeapNumber__HeapObject", 0x0 }, - { "v8dbg_parent_HeapObject__Object", 0x0 }, - { "v8dbg_parent_InterceptorInfo__Struct", 0x0 }, - { "v8dbg_parent_JSArray__JSObject", 0x0 }, - { "v8dbg_parent_JSBuiltinsObject__GlobalObject", 0x0 }, - { "v8dbg_parent_JSFunction__JSObject", 0x0 }, - { "v8dbg_parent_JSFunctionResultCache__FixedArray", 0x0 }, - { "v8dbg_parent_JSGlobalObject__GlobalObject", 0x0 }, - { "v8dbg_parent_JSGlobalPropertyCell__HeapObject", 0x0 }, - { "v8dbg_parent_JSGlobalProxy__JSObject", 0x0 }, - { "v8dbg_parent_JSMessageObject__JSObject", 0x0 }, - { "v8dbg_parent_JSObject__HeapObject", 0x0 }, - { "v8dbg_parent_JSRegExp__JSObject", 0x0 }, - { "v8dbg_parent_JSRegExpResult__JSArray", 0x0 }, - { "v8dbg_parent_JSValue__JSObject", 0x0 }, - { "v8dbg_parent_Map__HeapObject", 0x0 }, - { "v8dbg_parent_NormalizedMapCache__FixedArray", 0x0 }, - { "v8dbg_parent_Object__MaybeObject", 0x0 }, - { "v8dbg_parent_ObjectTemplateInfo__TemplateInfo", 0x0 }, - { "v8dbg_parent_Oddball__HeapObject", 0x0 }, - { "v8dbg_parent_Script__Struct", 0x0 }, - { "v8dbg_parent_SeqAsciiString__SeqString", 0x0 }, - { "v8dbg_parent_SeqString__String", 0x0 }, - { "v8dbg_parent_SeqTwoByteString__SeqString", 0x0 }, - { "v8dbg_parent_SharedFunctionInfo__HeapObject", 0x0 }, - { "v8dbg_parent_SignatureInfo__Struct", 0x0 }, - { "v8dbg_parent_Smi__Object", 0x0 }, - { "v8dbg_parent_String__HeapObject", 0x0 }, - { "v8dbg_parent_Struct__HeapObject", 0x0 }, - { "v8dbg_parent_TemplateInfo__Struct", 0x0 }, - { "v8dbg_parent_TypeSwitchInfo__Struct", 0x0 }, - - { "v8dbg_frametype_ArgumentsAdaptorFrame", 0x8 }, - { "v8dbg_frametype_ConstructFrame", 0x7 }, - { "v8dbg_frametype_EntryConstructFrame", 0x2 }, - { "v8dbg_frametype_EntryFrame", 0x1 }, - { "v8dbg_frametype_ExitFrame", 0x3 }, - { "v8dbg_frametype_InternalFrame", 0x6 }, - { "v8dbg_frametype_JavaScriptFrame", 0x4 }, - { "v8dbg_frametype_OptimizedFrame", 0x5 }, - - { "v8dbg_off_fp_context", -0x4 }, - { "v8dbg_off_fp_function", -0x8 }, - { "v8dbg_off_fp_marker", -0x8 }, - { "v8dbg_off_fp_args", 0x8 }, - - { "v8dbg_prop_idx_content", 0x0 }, - { "v8dbg_prop_idx_first", 0x2 }, - { "v8dbg_prop_type_field", 0x1 }, - { "v8dbg_prop_type_first_phantom", 0x6 }, - { "v8dbg_prop_type_mask", 0xf }, - - { "v8dbg_AsciiStringTag", 0x4 }, - { "v8dbg_ConsStringTag", 0x1 }, - { "v8dbg_ExternalStringTag", 0x2 }, - { "v8dbg_FailureTag", 0x3 }, - { "v8dbg_FailureTagMask", 0x3 }, - { "v8dbg_FirstNonstringType", 0x80 }, - { "v8dbg_HeapObjectTag", 0x1 }, - { "v8dbg_HeapObjectTagMask", 0x3 }, - { "v8dbg_IsNotStringMask", 0x80 }, - { "v8dbg_NotStringTag", 0x80 }, - { "v8dbg_SeqStringTag", 0x0 }, - { "v8dbg_SmiTag", 0x0 }, - { "v8dbg_SmiTagMask", 0x1 }, - { "v8dbg_SmiValueShift", 0x1 }, - { "v8dbg_StringEncodingMask", 0x4 }, - { "v8dbg_StringRepresentationMask", 0x3 }, - { "v8dbg_StringTag", 0x0 }, - { "v8dbg_TwoByteStringTag", 0x0 }, - { "v8dbg_PointerSizeLog2", 0x2 }, - - { NULL } -}; - -/* - * Canned configuration for the V8 bundled with Node.js v0.6.5. - */ -static v8_cfg_symbol_t v8_symbols_node_06[] = { - { "v8dbg_type_AccessCheckInfo__ACCESS_CHECK_INFO_TYPE", 0x93 }, - { "v8dbg_type_AccessorInfo__ACCESSOR_INFO_TYPE", 0x92 }, - { "v8dbg_type_BreakPointInfo__BREAK_POINT_INFO_TYPE", 0x9e }, - { "v8dbg_type_ByteArray__BYTE_ARRAY_TYPE", 0x86 }, - { "v8dbg_type_CallHandlerInfo__CALL_HANDLER_INFO_TYPE", 0x95 }, - { "v8dbg_type_Code__CODE_TYPE", 0x81 }, - { "v8dbg_type_CodeCache__CODE_CACHE_TYPE", 0x9b }, - { "v8dbg_type_ConsString__CONS_ASCII_STRING_TYPE", 0x5 }, - { "v8dbg_type_ConsString__CONS_ASCII_SYMBOL_TYPE", 0x45 }, - { "v8dbg_type_ConsString__CONS_STRING_TYPE", 0x1 }, - { "v8dbg_type_ConsString__CONS_SYMBOL_TYPE", 0x41 }, - { "v8dbg_type_DebugInfo__DEBUG_INFO_TYPE", 0x9d }, - { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_STRING_TYPE", 0x6 }, - { "v8dbg_type_ExternalAsciiString__EXTERNAL_ASCII_SYMBOL_TYPE", 0x46 }, - { "v8dbg_type_ExternalByteArray__EXTERNAL_BYTE_ARRAY_TYPE", 0x87 }, - { "v8dbg_type_ExternalDoubleArray__EXTERNAL_DOUBLE_ARRAY_TYPE", 0x8e }, - { "v8dbg_type_ExternalFloatArray__EXTERNAL_FLOAT_ARRAY_TYPE", 0x8d }, - { "v8dbg_type_ExternalIntArray__EXTERNAL_INT_ARRAY_TYPE", 0x8b }, - { "v8dbg_type_ExternalPixelArray__EXTERNAL_PIXEL_ARRAY_TYPE", 0x8f }, - { "v8dbg_type_ExternalShortArray__EXTERNAL_SHORT_ARRAY_TYPE", 0x89 }, - { "v8dbg_type_ExternalTwoByteString__EXTERNAL_STRING_TYPE", 0x2 }, - { "v8dbg_type_ExternalTwoByteString__EXTERNAL_SYMBOL_TYPE", 0x42 }, - { "v8dbg_type_ExternalUnsignedByteArray__" - "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE", 0x88 }, - { "v8dbg_type_ExternalUnsignedIntArray__" - "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE", 0x8c }, - { "v8dbg_type_ExternalUnsignedShortArray__" - "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE", 0x8a }, - { "v8dbg_type_FixedArray__FIXED_ARRAY_TYPE", 0x9f }, - { "v8dbg_type_FixedDoubleArray__FIXED_DOUBLE_ARRAY_TYPE", 0x90 }, - { "v8dbg_type_Foreign__FOREIGN_TYPE", 0x85 }, - { "v8dbg_type_FunctionTemplateInfo__FUNCTION_TEMPLATE_INFO_TYPE", - 0x96 }, - { "v8dbg_type_HeapNumber__HEAP_NUMBER_TYPE", 0x84 }, - { "v8dbg_type_InterceptorInfo__INTERCEPTOR_INFO_TYPE", 0x94 }, - { "v8dbg_type_JSArray__JS_ARRAY_TYPE", 0xa8 }, - { "v8dbg_type_JSBuiltinsObject__JS_BUILTINS_OBJECT_TYPE", 0xa6 }, - { "v8dbg_type_JSFunction__JS_FUNCTION_TYPE", 0xac }, - { "v8dbg_type_JSFunctionProxy__JS_FUNCTION_PROXY_TYPE", 0xad }, - { "v8dbg_type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE", 0xa5 }, - { "v8dbg_type_JSGlobalPropertyCell__JS_GLOBAL_PROPERTY_CELL_TYPE", - 0x83 }, - { "v8dbg_type_JSMessageObject__JS_MESSAGE_OBJECT_TYPE", 0xa1 }, - { "v8dbg_type_JSObject__JS_OBJECT_TYPE", 0xa3 }, - { "v8dbg_type_JSProxy__JS_PROXY_TYPE", 0xa9 }, - { "v8dbg_type_JSRegExp__JS_REGEXP_TYPE", 0xab }, - { "v8dbg_type_JSValue__JS_VALUE_TYPE", 0xa2 }, - { "v8dbg_type_JSWeakMap__JS_WEAK_MAP_TYPE", 0xaa }, - { "v8dbg_type_Map__MAP_TYPE", 0x80 }, - { "v8dbg_type_ObjectTemplateInfo__OBJECT_TEMPLATE_INFO_TYPE", 0x97 }, - { "v8dbg_type_Oddball__ODDBALL_TYPE", 0x82 }, - { "v8dbg_type_PolymorphicCodeCache__POLYMORPHIC_CODE_CACHE_TYPE", - 0x9c }, - { "v8dbg_type_Script__SCRIPT_TYPE", 0x9a }, - { "v8dbg_type_SeqAsciiString__ASCII_STRING_TYPE", 0x4 }, - { "v8dbg_type_SeqAsciiString__ASCII_SYMBOL_TYPE", 0x44 }, - { "v8dbg_type_SeqTwoByteString__STRING_TYPE", 0x0 }, - { "v8dbg_type_SeqTwoByteString__SYMBOL_TYPE", 0x40 }, - { "v8dbg_type_SharedFunctionInfo__SHARED_FUNCTION_INFO_TYPE", 0xa0 }, - { "v8dbg_type_SignatureInfo__SIGNATURE_INFO_TYPE", 0x98 }, - { "v8dbg_type_SlicedString__SLICED_ASCII_STRING_TYPE", 0x7 }, - { "v8dbg_type_SlicedString__SLICED_STRING_TYPE", 0x3 }, - { "v8dbg_type_TypeSwitchInfo__TYPE_SWITCH_INFO_TYPE", 0x99 }, - - { "v8dbg_class_AccessCheckInfo__data__Object", 0xc }, - { "v8dbg_class_AccessCheckInfo__indexed_callback__Object", 0x8 }, - { "v8dbg_class_AccessCheckInfo__named_callback__Object", 0x4 }, - { "v8dbg_class_AccessorInfo__data__Object", 0xc }, - { "v8dbg_class_AccessorInfo__flag__Smi", 0x14 }, - { "v8dbg_class_AccessorInfo__getter__Object", 0x4 }, - { "v8dbg_class_AccessorInfo__name__Object", 0x10 }, - { "v8dbg_class_AccessorInfo__setter__Object", 0x8 }, - { "v8dbg_class_BreakPointInfo__break_point_objects__Object", 0x10 }, - { "v8dbg_class_BreakPointInfo__code_position__Smi", 0x4 }, - { "v8dbg_class_BreakPointInfo__source_position__Smi", 0x8 }, - { "v8dbg_class_BreakPointInfo__statement_position__Smi", 0xc }, - { "v8dbg_class_CallHandlerInfo__callback__Object", 0x4 }, - { "v8dbg_class_CallHandlerInfo__data__Object", 0x8 }, - { "v8dbg_class_Code__deoptimization_data__FixedArray", 0xc }, - { "v8dbg_class_Code__instruction_size__int", 0x4 }, - { "v8dbg_class_Code__instruction_start__int", 0x20 }, - { "v8dbg_class_Code__next_code_flushing_candidate__Object", 0x10 }, - { "v8dbg_class_Code__relocation_info__ByteArray", 0x8 }, - { "v8dbg_class_CodeCache__default_cache__FixedArray", 0x4 }, - { "v8dbg_class_CodeCache__normal_type_cache__Object", 0x8 }, - { "v8dbg_class_ConsString__first__String", 0xc }, - { "v8dbg_class_ConsString__second__String", 0x10 }, - { "v8dbg_class_DebugInfo__break_points__FixedArray", 0x14 }, - { "v8dbg_class_DebugInfo__code__Code", 0xc }, - { "v8dbg_class_DebugInfo__original_code__Code", 0x8 }, - { "v8dbg_class_DebugInfo__shared__SharedFunctionInfo", 0x4 }, - { "v8dbg_class_ExternalString__resource__Object", 0xc }, - { "v8dbg_class_FixedArray__data__uintptr_t", 0x8 }, - { "v8dbg_class_FixedArrayBase__length__SMI", 0x4 }, - { "v8dbg_class_FunctionTemplateInfo__access_check_info__Object", 0x38 }, - { "v8dbg_class_FunctionTemplateInfo__call_code__Object", 0x10 }, - { "v8dbg_class_FunctionTemplateInfo__class_name__Object", 0x2c }, - { "v8dbg_class_FunctionTemplateInfo__flag__Smi", 0x3c }, - { "v8dbg_class_FunctionTemplateInfo__indexed_property_handler__Object", - 0x24 }, - { "v8dbg_class_FunctionTemplateInfo__instance_call_handler__Object", - 0x34 }, - { "v8dbg_class_FunctionTemplateInfo__instance_template__Object", 0x28 }, - { "v8dbg_class_FunctionTemplateInfo__named_property_handler__Object", - 0x20 }, - { "v8dbg_class_FunctionTemplateInfo__parent_template__Object", 0x1c }, - { "v8dbg_class_FunctionTemplateInfo__property_accessors__Object", - 0x14 }, - { "v8dbg_class_FunctionTemplateInfo__prototype_template__Object", - 0x18 }, - { "v8dbg_class_FunctionTemplateInfo__serial_number__Object", 0xc }, - { "v8dbg_class_FunctionTemplateInfo__signature__Object", 0x30 }, - { "v8dbg_class_GlobalObject__builtins__JSBuiltinsObject", 0xc }, - { "v8dbg_class_GlobalObject__global_context__Context", 0x10 }, - { "v8dbg_class_GlobalObject__global_receiver__JSObject", 0x14 }, - { "v8dbg_class_HeapNumber__value__double", 0x4 }, - { "v8dbg_class_HeapObject__map__Map", 0x0 }, - { "v8dbg_class_InterceptorInfo__data__Object", 0x18 }, - { "v8dbg_class_InterceptorInfo__deleter__Object", 0x10 }, - { "v8dbg_class_InterceptorInfo__enumerator__Object", 0x14 }, - { "v8dbg_class_InterceptorInfo__getter__Object", 0x4 }, - { "v8dbg_class_InterceptorInfo__query__Object", 0xc }, - { "v8dbg_class_InterceptorInfo__setter__Object", 0x8 }, - { "v8dbg_class_JSArray__length__Object", 0xc }, - { "v8dbg_class_JSFunction__literals__FixedArray", 0x1c }, - { "v8dbg_class_JSFunction__next_function_link__Object", 0x20 }, - { "v8dbg_class_JSFunction__prototype_or_initial_map__Object", 0x10 }, - { "v8dbg_class_JSFunction__shared__SharedFunctionInfo", 0x14 }, - { "v8dbg_class_JSFunctionProxy__call_trap__Object", 0x8 }, - { "v8dbg_class_JSFunctionProxy__construct_trap__Object", 0xc }, - { "v8dbg_class_JSGlobalProxy__context__Object", 0xc }, - { "v8dbg_class_JSMessageObject__arguments__JSArray", 0x10 }, - { "v8dbg_class_JSMessageObject__end_position__SMI", 0x24 }, - { "v8dbg_class_JSMessageObject__script__Object", 0x14 }, - { "v8dbg_class_JSMessageObject__stack_frames__Object", 0x1c }, - { "v8dbg_class_JSMessageObject__stack_trace__Object", 0x18 }, - { "v8dbg_class_JSMessageObject__start_position__SMI", 0x20 }, - { "v8dbg_class_JSMessageObject__type__String", 0xc }, - { "v8dbg_class_JSObject__elements__Object", 0x8 }, - { "v8dbg_class_JSObject__properties__FixedArray", 0x4 }, - { "v8dbg_class_JSProxy__handler__Object", 0x4 }, - { "v8dbg_class_JSRegExp__data__Object", 0xc }, - { "v8dbg_class_JSValue__value__Object", 0xc }, - { "v8dbg_class_JSWeakMap__next__Object", 0x10 }, - { "v8dbg_class_JSWeakMap__table__ObjectHashTable", 0xc }, - { "v8dbg_class_Map__code_cache__Object", 0x18 }, - { "v8dbg_class_Map__constructor__Object", 0x10 }, - { "v8dbg_class_Map__inobject_properties__int", 0x5 }, - { "v8dbg_class_Map__instance_attributes__int", 0x8 }, - { "v8dbg_class_Map__instance_descriptors__FixedArray", 0x14 }, - { "v8dbg_class_Map__instance_size__int", 0x4 }, - { "v8dbg_class_Map__prototype_transitions__FixedArray", 0x1c }, - { "v8dbg_class_ObjectTemplateInfo__constructor__Object", 0xc }, - { "v8dbg_class_ObjectTemplateInfo__internal_field_count__Object", - 0x10 }, - { "v8dbg_class_Oddball__to_number__Object", 0x8 }, - { "v8dbg_class_Oddball__to_string__String", 0x4 }, - { "v8dbg_class_PolymorphicCodeCache__cache__Object", 0x4 }, - { "v8dbg_class_Script__column_offset__Smi", 0x10 }, - { "v8dbg_class_Script__compilation_type__Smi", 0x24 }, - { "v8dbg_class_Script__context_data__Object", 0x18 }, - { "v8dbg_class_Script__data__Object", 0x14 }, - { "v8dbg_class_Script__eval_from_instructions_offset__Smi", 0x34 }, - { "v8dbg_class_Script__eval_from_shared__Object", 0x30 }, - { "v8dbg_class_Script__id__Object", 0x2c }, - { "v8dbg_class_Script__line_ends__Object", 0x28 }, - { "v8dbg_class_Script__line_offset__Smi", 0xc }, - { "v8dbg_class_Script__name__Object", 0x8 }, - { "v8dbg_class_Script__source__Object", 0x4 }, - { "v8dbg_class_Script__type__Smi", 0x20 }, - { "v8dbg_class_Script__wrapper__Foreign", 0x1c }, - { "v8dbg_class_SeqAsciiString__chars__char", 0xc }, - { "v8dbg_class_SharedFunctionInfo__code__Code", 0x8 }, - { "v8dbg_class_SharedFunctionInfo__compiler_hints__SMI", 0x50 }, - { "v8dbg_class_SharedFunctionInfo__construct_stub__Code", 0x10 }, - { "v8dbg_class_SharedFunctionInfo__debug_info__Object", 0x20 }, - { "v8dbg_class_SharedFunctionInfo__end_position__SMI", 0x48 }, - { "v8dbg_class_SharedFunctionInfo__expected_nof_properties__SMI", - 0x3c }, - { "v8dbg_class_SharedFunctionInfo__formal_parameter_count__SMI", 0x38 }, - { "v8dbg_class_SharedFunctionInfo__function_data__Object", 0x18 }, - { "v8dbg_class_SharedFunctionInfo__function_token_position__SMI", - 0x4c }, - { "v8dbg_class_SharedFunctionInfo__inferred_name__String", 0x24 }, - { "v8dbg_class_SharedFunctionInfo__initial_map__Object", 0x28 }, - { "v8dbg_class_SharedFunctionInfo__instance_class_name__Object", 0x14 }, - { "v8dbg_class_SharedFunctionInfo__length__SMI", 0x34 }, - { "v8dbg_class_SharedFunctionInfo__name__Object", 0x4 }, - { "v8dbg_class_SharedFunctionInfo__num_literals__SMI", 0x40 }, - { "v8dbg_class_SharedFunctionInfo__opt_count__SMI", 0x58 }, - { "v8dbg_class_SharedFunctionInfo__script__Object", 0x1c }, - { "v8dbg_class_SharedFunctionInfo__" - "start_position_and_type__SMI", 0x44 }, - { "v8dbg_class_SharedFunctionInfo__" - "this_property_assignments__Object", 0x2c }, - { "v8dbg_class_SharedFunctionInfo__" - "this_property_assignments_count__SMI", 0x54 }, - { "v8dbg_class_SignatureInfo__args__Object", 0x8 }, - { "v8dbg_class_SignatureInfo__receiver__Object", 0x4 }, - { "v8dbg_class_SlicedString__offset__SMI", 0x10 }, - { "v8dbg_class_String__length__SMI", 0x4 }, - { "v8dbg_class_TemplateInfo__property_list__Object", 0x8 }, - { "v8dbg_class_TemplateInfo__tag__Object", 0x4 }, - { "v8dbg_class_TypeSwitchInfo__types__Object", 0x4 }, - - { "v8dbg_parent_AccessCheckInfo__Struct", 0x0 }, - { "v8dbg_parent_AccessorInfo__Struct", 0x0 }, - { "v8dbg_parent_BreakPointInfo__Struct", 0x0 }, - { "v8dbg_parent_ByteArray__FixedArrayBase", 0x0 }, - { "v8dbg_parent_CallHandlerInfo__Struct", 0x0 }, - { "v8dbg_parent_Code__HeapObject", 0x0 }, - { "v8dbg_parent_CodeCache__Struct", 0x0 }, - { "v8dbg_parent_ConsString__String", 0x0 }, - { "v8dbg_parent_DebugInfo__Struct", 0x0 }, - { "v8dbg_parent_DeoptimizationInputData__FixedArray", 0x0 }, - { "v8dbg_parent_DeoptimizationOutputData__FixedArray", 0x0 }, - { "v8dbg_parent_DescriptorArray__FixedArray", 0x0 }, - { "v8dbg_parent_ExternalArray__FixedArrayBase", 0x0 }, - { "v8dbg_parent_ExternalAsciiString__ExternalString", 0x0 }, - { "v8dbg_parent_ExternalByteArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalDoubleArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalFloatArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalIntArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalPixelArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalShortArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalString__String", 0x0 }, - { "v8dbg_parent_ExternalTwoByteString__ExternalString", 0x0 }, - { "v8dbg_parent_ExternalUnsignedByteArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalUnsignedIntArray__ExternalArray", 0x0 }, - { "v8dbg_parent_ExternalUnsignedShortArray__ExternalArray", 0x0 }, - { "v8dbg_parent_Failure__MaybeObject", 0x0 }, - { "v8dbg_parent_FixedArray__FixedArrayBase", 0x0 }, - { "v8dbg_parent_FixedArrayBase__HeapObject", 0x0 }, - { "v8dbg_parent_FixedDoubleArray__FixedArrayBase", 0x0 }, - { "v8dbg_parent_Foreign__HeapObject", 0x0 }, - { "v8dbg_parent_FunctionTemplateInfo__TemplateInfo", 0x0 }, - { "v8dbg_parent_GlobalObject__JSObject", 0x0 }, - { "v8dbg_parent_HashTable__FixedArray", 0x0 }, - { "v8dbg_parent_HeapNumber__HeapObject", 0x0 }, - { "v8dbg_parent_HeapObject__Object", 0x0 }, - { "v8dbg_parent_InterceptorInfo__Struct", 0x0 }, - { "v8dbg_parent_JSArray__JSObject", 0x0 }, - { "v8dbg_parent_JSBuiltinsObject__GlobalObject", 0x0 }, - { "v8dbg_parent_JSFunction__JSObject", 0x0 }, - { "v8dbg_parent_JSFunctionProxy__JSProxy", 0x0 }, - { "v8dbg_parent_JSFunctionResultCache__FixedArray", 0x0 }, - { "v8dbg_parent_JSGlobalObject__GlobalObject", 0x0 }, - { "v8dbg_parent_JSGlobalPropertyCell__HeapObject", 0x0 }, - { "v8dbg_parent_JSMessageObject__JSObject", 0x0 }, - { "v8dbg_parent_JSObject__JSReceiver", 0x0 }, - { "v8dbg_parent_JSProxy__JSReceiver", 0x0 }, - { "v8dbg_parent_JSReceiver__HeapObject", 0x0 }, - { "v8dbg_parent_JSRegExp__JSObject", 0x0 }, - { "v8dbg_parent_JSRegExpResult__JSArray", 0x0 }, - { "v8dbg_parent_JSValue__JSObject", 0x0 }, - { "v8dbg_parent_JSWeakMap__JSObject", 0x0 }, - { "v8dbg_parent_Map__HeapObject", 0x0 }, - { "v8dbg_parent_NormalizedMapCache__FixedArray", 0x0 }, - { "v8dbg_parent_ObjectTemplateInfo__TemplateInfo", 0x0 }, - { "v8dbg_parent_Oddball__HeapObject", 0x0 }, - { "v8dbg_parent_PolymorphicCodeCache__Struct", 0x0 }, - { "v8dbg_parent_Script__Struct", 0x0 }, - { "v8dbg_parent_SeqAsciiString__SeqString", 0x0 }, - { "v8dbg_parent_SeqString__String", 0x0 }, - { "v8dbg_parent_SeqTwoByteString__SeqString", 0x0 }, - { "v8dbg_parent_SharedFunctionInfo__HeapObject", 0x0 }, - { "v8dbg_parent_SignatureInfo__Struct", 0x0 }, - { "v8dbg_parent_SlicedString__String", 0x0 }, - { "v8dbg_parent_Smi__Object", 0x0 }, - { "v8dbg_parent_String__HeapObject", 0x0 }, - { "v8dbg_parent_Struct__HeapObject", 0x0 }, - { "v8dbg_parent_TemplateInfo__Struct", 0x0 }, - { "v8dbg_parent_TypeSwitchInfo__Struct", 0x0 }, - - { "v8dbg_frametype_ArgumentsAdaptorFrame", 0x8 }, - { "v8dbg_frametype_ConstructFrame", 0x7 }, - { "v8dbg_frametype_EntryConstructFrame", 0x2 }, - { "v8dbg_frametype_EntryFrame", 0x1 }, - { "v8dbg_frametype_ExitFrame", 0x3 }, - { "v8dbg_frametype_InternalFrame", 0x6 }, - { "v8dbg_frametype_JavaScriptFrame", 0x4 }, - { "v8dbg_frametype_OptimizedFrame", 0x5 }, - - { "v8dbg_off_fp_args", 0x8 }, - { "v8dbg_off_fp_context", -0x4 }, - { "v8dbg_off_fp_function", -0x8 }, - { "v8dbg_off_fp_marker", -0x8 }, - - { "v8dbg_prop_idx_content", 0x1 }, - { "v8dbg_prop_idx_first", 0x3 }, - { "v8dbg_prop_type_field", 0x1 }, - { "v8dbg_prop_type_first_phantom", 0x6 }, - { "v8dbg_prop_type_mask", 0xf }, - - { "v8dbg_AsciiStringTag", 0x4 }, - { "v8dbg_PointerSizeLog2", 0x2 }, - { "v8dbg_SeqStringTag", 0x0 }, - { "v8dbg_SmiTag", 0x0 }, - { "v8dbg_SmiTagMask", 0x1 }, - { "v8dbg_SmiValueShift", 0x1 }, - { "v8dbg_StringEncodingMask", 0x4 }, - { "v8dbg_StringRepresentationMask", 0x3 }, - { "v8dbg_StringTag", 0x0 }, - { "v8dbg_TwoByteStringTag", 0x0 }, - { "v8dbg_ConsStringTag", 0x1 }, - { "v8dbg_ExternalStringTag", 0x2 }, - { "v8dbg_FailureTag", 0x3 }, - { "v8dbg_FailureTagMask", 0x3 }, - { "v8dbg_FirstNonstringType", 0x80 }, - { "v8dbg_HeapObjectTag", 0x1 }, - { "v8dbg_HeapObjectTagMask", 0x3 }, - { "v8dbg_IsNotStringMask", 0x80 }, - { "v8dbg_NotStringTag", 0x80 }, - - { NULL }, -}; - -v8_cfg_t v8_cfg_04 = { "node-0.4", "node v0.4", v8_symbols_node_04, - v8cfg_canned_iter, v8cfg_canned_readsym }; - -v8_cfg_t v8_cfg_06 = { "node-0.6", "node v0.6", v8_symbols_node_06, - v8cfg_canned_iter, v8cfg_canned_readsym }; - -v8_cfg_t *v8_cfgs[] = { - &v8_cfg_04, - &v8_cfg_06, - NULL -}; - -v8_cfg_t v8_cfg_target = { NULL, NULL, NULL, v8cfg_target_iter, - v8cfg_target_readsym }; diff --git a/deps/mdb_v8/v8cfg.h b/deps/mdb_v8/v8cfg.h deleted file mode 100644 index 8c5231e425..0000000000 --- a/deps/mdb_v8/v8cfg.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * v8cfg.h: canned configurations for previous V8 versions - */ - -#ifndef V8CFG_H -#define V8CFG_H - -#include -#include - -typedef struct { - const char *v8cs_name; /* symbol name */ - intptr_t v8cs_value; /* symbol value */ -} v8_cfg_symbol_t; - -typedef struct v8_cfg { - const char *v8cfg_name; /* canned config name */ - const char *v8cfg_label; /* description */ - v8_cfg_symbol_t *v8cfg_symbols; /* actual symbol values */ - - int (*v8cfg_iter)(struct v8_cfg *, int (*)(mdb_symbol_t *, void *), - void *); - int (*v8cfg_readsym)(struct v8_cfg *, const char *, intptr_t *); -} v8_cfg_t; - -extern v8_cfg_t v8_cfg_04; -extern v8_cfg_t v8_cfg_06; -extern v8_cfg_t v8_cfg_target; -extern v8_cfg_t *v8_cfgs[]; - -#endif /* V8CFG_H */ diff --git a/deps/mdb_v8/v8dbg.h b/deps/mdb_v8/v8dbg.h deleted file mode 100644 index a66329eacb..0000000000 --- a/deps/mdb_v8/v8dbg.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * v8dbg.h: macros for use by V8 heap inspection tools. The consumer must - * define values for various tags and shifts. The MDB module gets these - * constants from information encoded in the binary itself. - */ - -#ifndef _V8DBG_H -#define _V8DBG_H - -/* - * Recall that while V8 heap objects are always 4-byte aligned, heap object - * pointers always have the last bit set. So when looking for a field nominally - * at offset X, one must be sure to clear the tag bit first. - */ -#define V8_OFF_HEAP(x) ((x) - V8_HeapObjectTag) - -/* - * Determine whether a given pointer refers to a SMI, Failure, or HeapObject. - */ -#define V8_IS_SMI(ptr) (((ptr) & V8_SmiTagMask) == V8_SmiTag) -#define V8_IS_FAILURE(ptr) (((ptr) & V8_FailureTagMask) == V8_FailureTag) -#define V8_IS_HEAPOBJECT(ptr) \ - (((ptr) & V8_HeapObjectTagMask) == V8_HeapObjectTag) - -/* - * Extract the value of a SMI "pointer". Recall that small integers are stored - * using the upper 31 bits. - */ -#define V8_SMI_VALUE(smi) ((smi) >> (V8_SmiValueShift + V8_SmiShiftSize)) - -/* - * Determine the encoding and representation of a V8 string. - */ -#define V8_TYPE_STRING(type) (((type) & V8_IsNotStringMask) == V8_StringTag) - -#define V8_STRENC_ASCII(type) \ - (((type) & V8_StringEncodingMask) == V8_AsciiStringTag) - -#define V8_STRREP_SEQ(type) \ - (((type) & V8_StringRepresentationMask) == V8_SeqStringTag) -#define V8_STRREP_CONS(type) \ - (((type) & V8_StringRepresentationMask) == V8_ConsStringTag) -#define V8_STRREP_SLICED(type) \ - (((type) & V8_StringRepresentationMask) == V8_SlicedStringTag) -#define V8_STRREP_EXT(type) \ - (((type) & V8_StringRepresentationMask) == V8_ExternalStringTag) - -/* - * Several of the following constants and transformations are hardcoded in V8 as - * well, so there's no way to extract them programmatically from the binary. - */ -#define V8_DESC_KEYIDX(x) ((x) + V8_PROP_IDX_FIRST) -#define V8_DESC_VALIDX(x) ((x) << 1) -#define V8_DESC_DETIDX(x) (((x) << 1) + 1) - -#define V8_DESC_ISFIELD(x) \ - ((V8_SMI_VALUE(x) & V8_PROP_TYPE_MASK) == V8_PROP_TYPE_FIELD) - -#endif /* _V8DBG_H */ diff --git a/node.gyp b/node.gyp index 34c3033758..cae5340b27 100644 --- a/node.gyp +++ b/node.gyp @@ -12,7 +12,6 @@ 'node_shared_libuv%': 'false', 'node_use_openssl%': 'true', 'node_shared_openssl%': 'false', - 'node_use_mdb%': 'false', 'node_v8_options%': '', 'library_files': [ 'src/node.js', @@ -275,13 +274,6 @@ 'src/node_lttng.cc' ], } ], - [ 'node_use_mdb=="true"', { - 'dependencies': [ 'node_mdb' ], - 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ], - 'sources': [ - 'src/node_mdb.cc', - ], - } ], [ 'node_use_etw=="true"', { 'defines': [ 'HAVE_ETW=1' ], 'dependencies': [ 'node_etw' ], @@ -509,32 +501,6 @@ } ], ] }, - { - 'target_name': 'node_mdb', - 'type': 'none', - 'conditions': [ - [ 'node_use_mdb=="true"', - { - 'dependencies': [ 'deps/mdb_v8/mdb_v8.gyp:mdb_v8' ], - 'actions': [ - { - 'action_name': 'node_mdb', - 'inputs': [ '<(PRODUCT_DIR)/obj.target/deps/mdb_v8/mdb_v8.so' ], - 'outputs': [ '<(PRODUCT_DIR)/obj.target/node/src/node_mdb.o' ], - 'conditions': [ - [ 'target_arch=="ia32"', { - 'action': [ 'elfwrap', '-o', '<@(_outputs)', '<@(_inputs)' ], - } ], - [ 'target_arch=="x64"', { - 'action': [ 'elfwrap', '-64', '-o', '<@(_outputs)', '<@(_inputs)' ], - } ], - ], - }, - ], - }, - ], - ], - }, { 'target_name': 'node_dtrace_provider', 'type': 'none', diff --git a/test/pummel/test-postmortem-findjsobjects.js b/test/pummel/test-postmortem-findjsobjects.js deleted file mode 100644 index 555d42aacd..0000000000 --- a/test/pummel/test-postmortem-findjsobjects.js +++ /dev/null @@ -1,86 +0,0 @@ -var common = require('../common'); -var assert = require('assert'); -var os = require('os'); -var path = require('path'); -var util = require('util'); - -if (os.type() != 'SunOS') { - console.error('Skipping because postmortem debugging not available.'); - process.exit(0); -} - -/* - * Now we're going to fork ourselves to gcore - */ -var spawn = require('child_process').spawn; -var prefix = '/var/tmp/node'; -var corefile = prefix + '.' + process.pid; -var gcore = spawn('gcore', [ '-o', prefix, process.pid + '' ]); -var output = ''; -var unlinkSync = require('fs').unlinkSync; -var args = [ corefile ]; - -if (process.env.MDB_LIBRARY_PATH && process.env.MDB_LIBRARY_PATH != '') - args = args.concat([ '-L', process.env.MDB_LIBRARY_PATH ]); - -function LanguageH(chapter) { this.OBEY = 'CHAPTER ' + parseInt(chapter, 10); } -var obj = new LanguageH(1); - -gcore.stderr.on('data', function (data) { - console.log('gcore: ' + data); -}); - -gcore.on('exit', function (code) { - if (code != 0) { - console.error('gcore exited with code ' + code); - process.exit(code); - } - - var mdb = spawn('mdb', args, { stdio: 'pipe' }); - - mdb.on('exit', function (code) { - var retained = '; core retained as ' + corefile; - - if (code != 0) { - console.error('mdb exited with code ' + util.inspect(code) + retained); - process.exit(code); - } - - var lines = output.split('\n'); - var found = 0, i, expected = 'OBEY: "' + obj.OBEY + '"', nexpected = 2; - - for (var i = 0; i < lines.length; i++) { - if (lines[i].indexOf(expected) != -1) - found++; - } - - assert.equal(found, nexpected, 'expected ' + nexpected + - ' objects, found ' + found + retained); - - unlinkSync(corefile); - process.exit(0); - }); - - mdb.stdout.on('data', function (data) { - output += data; - }); - - mdb.stderr.on('data', function (data) { - console.log('mdb stderr: ' + data); - }); - - var mod = util.format('::load %s\n', - path.join(__dirname, - '..', - '..', - 'out', - 'Release', - 'mdb_v8.so')); - mdb.stdin.write(mod); - mdb.stdin.write('::findjsobjects -c LanguageH | '); - mdb.stdin.write('::findjsobjects | ::jsprint\n'); - mdb.stdin.write('::findjsobjects -p OBEY | '); - mdb.stdin.write('::findjsobjects | ::jsprint\n'); - mdb.stdin.end(); -}); - diff --git a/test/pummel/test-postmortem-jsstack.js b/test/pummel/test-postmortem-jsstack.js deleted file mode 100644 index 784f3df041..0000000000 --- a/test/pummel/test-postmortem-jsstack.js +++ /dev/null @@ -1,166 +0,0 @@ -var common = require('../common'); -var assert = require('assert'); -var os = require('os'); -var util = require('util'); - -if (os.type() != 'SunOS') { - console.error('Skipping because postmortem debugging not available.'); - process.exit(0); -} - -/* - * Some functions to create a recognizable stack. - */ -var frames = [ 'stalloogle', 'bagnoogle', 'doogle' ]; -var expected; - -var stalloogle = function (str) { - expected = str; - os.loadavg(); -}; - -var bagnoogle = function (arg0, arg1) { - stalloogle(arg0 + ' is ' + arg1 + ' except that it is read-only'); -}; - -var done = false; - -var doogle = function () { - if (!done) - setTimeout(doogle, 10); - - bagnoogle('The bfs command', '(almost) like ed(1)'); -}; - -var spawn = require('child_process').spawn; -var prefix = '/var/tmp/node'; -var corefile = prefix + '.' + process.pid; -var args = [ corefile ]; - -if (process.env.MDB_LIBRARY_PATH && process.env.MDB_LIBRARY_PATH != '') - args = args.concat([ '-L', process.env.MDB_LIBRARY_PATH ]); - -/* - * We're going to use DTrace to stop us, gcore us, and set us running again - * when we call getloadavg() -- with the implicit assumption that our - * deepest function is the only caller of os.loadavg(). - */ -var dtrace = spawn('dtrace', [ '-qwn', 'syscall::getloadavg:entry/pid == ' + - process.pid + '/{stop(); system("gcore -o ' + - prefix + ' %d", pid); system("prun %d", pid); exit(0); }' ]); - -var output = ''; -var unlinkSync = require('fs').unlinkSync; - -dtrace.stderr.on('data', function (data) { - console.log('dtrace: ' + data); -}); - -dtrace.on('exit', function (code) { - if (code != 0) { - console.error('dtrace exited with code ' + code); - process.exit(code); - } - - done = true; - - /* - * We have our core file. Now we need to fire up mdb to analyze it... - */ - var mdb = spawn('mdb', args, { stdio: 'pipe' }); - - var mod = util.format('::load %s\n', - path.join(__dirname, - '..', - '..', - 'out', - 'Release', - 'mdb_v8.so')); - - mdb.on('exit', function (code) { - var retained = '; core retained as ' + corefile; - - if (code != 0) { - console.error('mdb exited with code ' + code + retained); - process.exit(code); - } - - var sentinel = ' (as '; - var arg1 = ' arg1: '; - var lines = output.split('\n'); - var matched = 0; - var straddr = undefined; - - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - - if (matched == 1 && line.indexOf(arg1) === 0) { - straddr = line.substr(arg1.length).split(' ')[0]; - } - - if (line.indexOf(sentinel) == -1 || frames.length === 0) - continue; - - var frame = line.substr(line.indexOf(sentinel) + sentinel.length); - var top = frames.shift(); - - assert.equal(frame.indexOf(top), 0, 'unexpected frame where ' + - top + ' was expected' + retained); - - matched++; - } - - assert.equal(frames.length, 0, 'did not find expected frame ' + - frames[0] + retained); - - assert.notEqual(straddr, undefined, - 'did not find arg1 for top frame' + retained); - - /* - * Now we're going to take one more swing at the core file to print out - * the argument string that we found. - */ - output = ''; - mdb = spawn('mdb', args, { stdio: 'pipe' }); - - mdb.on('exit', function (code) { - if (code != 0) { - console.error('mdb (second) exited with code ' + code + retained); - process.exit(code); - } - - assert.notEqual(output.indexOf(expected), -1, 'did not find arg1 (' + - straddr + ') to contain expected string' + retained); - - unlinkSync(corefile); - process.exit(0); - }); - - mdb.stdout.on('data', function (data) { - output += data; - }); - - mdb.stderr.on('data', function (data) { - console.log('mdb (second) stderr: ' + data); - }); - - mdb.stdin.write(mod); - mdb.stdin.write(straddr + '::v8str\n'); - mdb.stdin.end(); - }); - - mdb.stdout.on('data', function (data) { - output += data; - }); - - mdb.stderr.on('data', function (data) { - console.log('mdb stderr: ' + data); - }); - - mdb.stdin.write(mod); - mdb.stdin.write('::jsstack -v\n'); - mdb.stdin.end(); -}); - -setTimeout(doogle, 10); - diff --git a/tools/mdb/extract_dmod.c b/tools/mdb/extract_dmod.c deleted file mode 100644 index 0efc94a8f8..0000000000 --- a/tools/mdb/extract_dmod.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * gcc -Wall -lproc -o extract_dmod extract_dmod.c - * - * use this tool to extract the mdb_v8.so from a core file for use with older - * mdb or platforms with an out of date v8.so - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -const char *g_sym = "mdb_v8.so_start"; - -int -main(int argc, const char *argv[]) -{ - int ifd, ofd, perr, toread, ret; - struct ps_prochandle *p; - GElf_Sym sym; - prsyminfo_t si; - char buf[1024]; - - if (argc != 3) { - fprintf(stderr, "pdump: \n"); - return (1); - } - - ifd = open(argv[1], O_RDONLY); - if (ifd < 0) { - fprintf(stderr, "failed to open: %s: %s\n", - argv[1], strerror(errno)); - return (1); - } - ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC); - if (ofd < 0) { - fprintf(stderr, "failed to open: %s: %s\n", - argv[1], strerror(errno)); - return (1); - } - - p = Pfgrab_core(ifd, NULL, &perr); - if (p == NULL) { - fprintf(stderr, "failed to grab core file\n"); - return (1); - } - - if (Pxlookup_by_name(p, NULL, "a.out", g_sym, &sym, &si) != 0) { - fprintf(stderr, "failed to lookup symobl %s\n", g_sym); - return (0); - } - - while (sym.st_size > 0) { - toread = MIN(sym.st_size, sizeof (buf)); - ret = Pread(p, buf, toread, sym.st_value); - if (ret < 0) { - fprintf(stderr, "failed to Pread...\n"); - return (1); - } - if (ret != 0) - ret = write(ofd, buf, ret); - if (ret < 0) { - fprintf(stderr, "failed to write to output file %s\n", - strerror(errno)); - } - sym.st_size -= ret; - sym.st_value += ret; - } - - return (0); -}