mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
dtrace, mdb_v8: support more string, frame types
This change makes several improvements to the ustack helper and MDB support: - ustack helper and MDB: add support for two-byte strings (necessary to print many filenames in stacktraces in 0.10 and later). - ustack helper: fix position numbers, which were off by a factor of two - ustack helper: fix frames with undefined Scripts (e.g., "RegExp") - ustack helper: add stub frames - MDB: add support for sliced strings - MDB: sync up with changes from the illumos version of the module Fixes #6309 Closes #6318
This commit is contained in:
parent
406846fcc5
commit
5921158cbe
187
deps/mdb_v8/mdb_v8.c
vendored
187
deps/mdb_v8/mdb_v8.c
vendored
|
|
@ -24,6 +24,14 @@
|
|||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -119,6 +127,7 @@ 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;
|
||||
|
|
@ -180,12 +189,15 @@ static ssize_t V8_OFF_SCRIPT_LINE_ENDS;
|
|||
static ssize_t V8_OFF_SCRIPT_NAME;
|
||||
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_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 */
|
||||
|
|
@ -233,6 +245,8 @@ static v8_constant_t v8_constants[] = {
|
|||
{ &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" },
|
||||
|
|
@ -284,6 +298,7 @@ typedef struct v8_offset {
|
|||
const char *v8o_class;
|
||||
const char *v8o_member;
|
||||
boolean_t v8o_optional;
|
||||
intptr_t v8o_fallback;
|
||||
} v8_offset_t;
|
||||
|
||||
static v8_offset_t v8_offsets[] = {
|
||||
|
|
@ -339,6 +354,8 @@ static v8_offset_t v8_offsets[] = {
|
|||
"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_FUNCTION_TOKEN_POSITION,
|
||||
|
|
@ -351,6 +368,10 @@ static v8_offset_t v8_offsets[] = {
|
|||
"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" },
|
||||
};
|
||||
|
|
@ -516,6 +537,13 @@ again:
|
|||
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);
|
||||
|
||||
return (failed ? -1 : 0);
|
||||
}
|
||||
|
||||
|
|
@ -795,6 +823,7 @@ conf_class_compute_offsets(v8_class_t *clp)
|
|||
#define JSSTR_NUDE JSSTR_NONE
|
||||
#define JSSTR_VERBOSE 0x1
|
||||
#define JSSTR_QUOTED 0x2
|
||||
#define JSSTR_ISASCII 0x4
|
||||
|
||||
static int jsstr_print(uintptr_t, uint_t, char **, size_t *);
|
||||
static boolean_t jsobj_is_undefined(uintptr_t addr);
|
||||
|
|
@ -996,6 +1025,7 @@ read_heap_array(uintptr_t addr, uintptr_t **retp, size_t *lenp, int flags)
|
|||
if (!(flags & UM_GC))
|
||||
mdb_free(*retp, len * sizeof (uintptr_t));
|
||||
|
||||
*retp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
|
@ -1290,11 +1320,13 @@ obj_print_class(uintptr_t addr, v8_class_t *clp)
|
|||
}
|
||||
|
||||
/*
|
||||
* Print the ASCII string for the given ASCII JS string, expanding ConsStrings
|
||||
* and ExternalStrings as needed.
|
||||
* 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 *);
|
||||
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
|
||||
|
|
@ -1315,11 +1347,6 @@ jsstr_print(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp)
|
|||
return (0);
|
||||
}
|
||||
|
||||
if (!V8_STRENC_ASCII(typebyte)) {
|
||||
(void) bsnprintf(bufp, lenp, "<two-byte string>");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
lbufp = buf;
|
||||
llen = sizeof (buf);
|
||||
|
|
@ -1328,12 +1355,19 @@ jsstr_print(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp)
|
|||
(void) mdb_inc_indent(4);
|
||||
}
|
||||
|
||||
if (V8_STRENC_ASCII(typebyte))
|
||||
flags |= JSSTR_ISASCII;
|
||||
else
|
||||
flags &= ~JSSTR_ISASCII;
|
||||
|
||||
if (V8_STRREP_SEQ(typebyte))
|
||||
err = jsstr_print_seq(addr, flags, bufp, lenp);
|
||||
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, "<unknown string type>");
|
||||
err = -1;
|
||||
|
|
@ -1346,43 +1380,86 @@ jsstr_print(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp)
|
|||
}
|
||||
|
||||
static int
|
||||
jsstr_print_seq(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp)
|
||||
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 len, rlen, blen = *lenp + sizeof ("[...]") + 1;
|
||||
char *buf = alloca(MIN(blen, 256 * 1024));
|
||||
uintptr_t i, nstrchrs, nreadbytes, nreadoffset, blen, nstrbytes;
|
||||
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 (read_heap_smi(&len, addr, V8_OFF_STRING_LENGTH) != 0)
|
||||
blen = MIN(*lenp, 256 * 1024);
|
||||
buf = alloca(blen);
|
||||
|
||||
if (read_heap_smi(&nstrchrs, addr, V8_OFF_STRING_LENGTH) != 0)
|
||||
return (-1);
|
||||
|
||||
rlen = len <= blen - 1 ? len : blen - sizeof ("[...]");
|
||||
if (slicelen != -1)
|
||||
nstrchrs = slicelen;
|
||||
if (nstrchrs < 0)
|
||||
nstrchrs = 0;
|
||||
|
||||
if ((flags & JSSTR_ISASCII) != 0) {
|
||||
nstrbytes = nstrchrs;
|
||||
nreadoffset = sliceoffset;
|
||||
} else {
|
||||
nstrbytes = 2 * nstrchrs;
|
||||
nreadoffset = 2 * sliceoffset;
|
||||
}
|
||||
|
||||
nreadbytes = nstrbytes + sizeof ("\"\"") <= blen ? nstrbytes :
|
||||
blen - sizeof ("\"\"[...]");
|
||||
|
||||
if (verbose)
|
||||
mdb_printf("length: %d, will read: %d\n", len, rlen);
|
||||
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 (rlen > 0 && mdb_readstr(buf, rlen + 1,
|
||||
addr + V8_OFF_SEQASCIISTR_CHARS) == -1) {
|
||||
v8_warn("failed to read SeqString data");
|
||||
return (-1);
|
||||
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) {
|
||||
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 ? "\"" : "");
|
||||
}
|
||||
|
||||
if (rlen != len)
|
||||
(void) strlcat(buf, "[...]", blen);
|
||||
|
||||
if (verbose)
|
||||
mdb_printf("value: \"%s\"\n", buf);
|
||||
|
||||
(void) bsnprintf(bufp, lenp, "%s%s%s",
|
||||
quoted ? "\"" : "", buf, quoted ? "\"" : "");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -1418,14 +1495,64 @@ jsstr_print_cons(uintptr_t addr, uint_t flags, char **bufp, size_t *lenp)
|
|||
}
|
||||
|
||||
static int
|
||||
jsstr_print_external(uintptr_t addr, uint_t flags, char **bufp,
|
||||
size_t *lenp)
|
||||
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;
|
||||
uint_t newflags;
|
||||
|
||||
if (read_heap_ptr(&parent, addr, V8_OFF_SLICEDSTRING_PARENT) != 0 ||
|
||||
read_heap_smi(&offset, addr, V8_OFF_SLICEDSTRING_OFFSET) != 0 ||
|
||||
read_heap_smi(&length, addr, V8_OFF_STRING_LENGTH) != 0)
|
||||
return (-1);
|
||||
|
||||
if (verbose)
|
||||
mdb_printf("parent: %p, offset = %d, length = %d\n",
|
||||
parent, offset, length);
|
||||
|
||||
if (read_typebyte(&typebyte, parent) != 0) {
|
||||
v8_warn("SlicedString %s: failed to read parent's type", addr);
|
||||
(void) bsnprintf(bufp, lenp, "<sliced string>");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!V8_STRREP_SEQ(typebyte)) {
|
||||
v8_warn("SlicedString %s: parent is not a sequential string",
|
||||
addr);
|
||||
(void) bsnprintf(bufp, lenp, "<sliced string>");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (quoted)
|
||||
(void) bsnprintf(bufp, lenp, "\"");
|
||||
|
||||
newflags = verbose ? JSSTR_VERBOSE : 0;
|
||||
if (V8_STRENC_ASCII(typebyte))
|
||||
newflags |= JSSTR_ISASCII;
|
||||
if (jsstr_print_seq(parent, newflags, 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 = alloca(blen);
|
||||
boolean_t quoted = flags & JSSTR_QUOTED ? B_TRUE : B_FALSE;
|
||||
|
||||
if ((flags & JSSTR_ISASCII) == 0) {
|
||||
(void) bsnprintf(bufp, lenp, "<external two-byte string>");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (flags & JSSTR_VERBOSE)
|
||||
mdb_printf("assuming Node.js string\n");
|
||||
|
||||
|
|
|
|||
2
deps/mdb_v8/v8dbg.h
vendored
2
deps/mdb_v8/v8dbg.h
vendored
|
|
@ -61,6 +61,8 @@
|
|||
(((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)
|
||||
|
||||
|
|
|
|||
12
src/v8abbr.h
12
src/v8abbr.h
|
|
@ -42,6 +42,7 @@
|
|||
#define V8_FT_INTERNAL V8DBG_FRAMETYPE_INTERNALFRAME
|
||||
#define V8_FT_CONSTRUCT V8DBG_FRAMETYPE_CONSTRUCTFRAME
|
||||
#define V8_FT_ADAPTOR V8DBG_FRAMETYPE_ARGUMENTSADAPTORFRAME
|
||||
#define V8_FT_STUB V8DBG_FRAMETYPE_STUBFRAME
|
||||
|
||||
/* Identification masks and tags */
|
||||
#define V8_SmiTagMask (V8DBG_SMITAGMASK)
|
||||
|
|
@ -65,10 +66,19 @@
|
|||
/* Instance types */
|
||||
#define V8_IT_FIXEDARRAY V8DBG_TYPE_FIXEDARRAY__FIXED_ARRAY_TYPE
|
||||
#define V8_IT_CODE V8DBG_TYPE_CODE__CODE_TYPE
|
||||
#define V8_IT_SCRIPT V8DBG_TYPE_SCRIPT__SCRIPT_TYPE
|
||||
|
||||
/* Node-specific offsets */
|
||||
#define NODE_OFF_EXTSTR_DATA sizeof(void*)
|
||||
|
||||
/*
|
||||
* Not all versions of V8 have the offset for the "chars" array in the
|
||||
* SeqTwoByteString class, but it's the same as the one for SeqOneByteString.
|
||||
*/
|
||||
#ifndef V8DBG_CLASS_SEQTWOBYTESTRING__CHARS__CHAR
|
||||
#define V8DBG_CLASS_SEQTWOBYTESTRING__CHARS__CHAR V8DBG_CLASS_SEQONEBYTESTRING__CHARS__CHAR
|
||||
#endif
|
||||
|
||||
/* Heap class->field offsets */
|
||||
#define V8_OFF_HEAP(off) ((off) - 1)
|
||||
|
||||
|
|
@ -104,5 +114,7 @@
|
|||
V8_OFF_HEAP(V8DBG_CLASS_HEAPOBJECT__MAP__MAP)
|
||||
#define V8_OFF_MAP_ATTRS \
|
||||
V8_OFF_HEAP(V8DBG_CLASS_MAP__INSTANCE_ATTRIBUTES__INT)
|
||||
#define V8_OFF_TWOBYTESTR_CHARS \
|
||||
V8_OFF_HEAP(V8DBG_CLASS_SEQTWOBYTESTRING__CHARS__CHAR)
|
||||
|
||||
#endif /* SRC_V8ABBR_H_ */
|
||||
|
|
|
|||
152
src/v8ustack.d
152
src/v8ustack.d
|
|
@ -31,6 +31,9 @@
|
|||
#define V8_MAP_PTR(ptr) \
|
||||
((ptr & ~V8_HeapObjectTagMask) | V8_HeapObjectTag)
|
||||
|
||||
#define V8_TYPE_SCRIPT(type) \
|
||||
((type) == V8_IT_SCRIPT)
|
||||
|
||||
/*
|
||||
* Determine the encoding and representation of a V8 string.
|
||||
*/
|
||||
|
|
@ -53,8 +56,11 @@
|
|||
#define ASCII_SEQSTR(value) \
|
||||
(V8_TYPE_STRING(value) && V8_STRENC_ASCII(value) && V8_STRREP_SEQ(value))
|
||||
|
||||
#define ASCII_CONSSTR(value) \
|
||||
(V8_TYPE_STRING(value) && V8_STRENC_ASCII(value) && V8_STRREP_CONS(value))
|
||||
#define TWOBYTE_SEQSTR(value) \
|
||||
(V8_TYPE_STRING(value) && !V8_STRENC_ASCII(value) && V8_STRREP_SEQ(value))
|
||||
|
||||
#define IS_CONSSTR(value) \
|
||||
(V8_TYPE_STRING(value) && V8_STRREP_CONS(value))
|
||||
|
||||
#define ASCII_EXTSTR(value) \
|
||||
(V8_TYPE_STRING(value) && V8_STRENC_ASCII(value) && V8_STRREP_EXT(value))
|
||||
|
|
@ -123,14 +129,16 @@
|
|||
* "len": the string length
|
||||
*
|
||||
* "attrs": the type identifier for the string, which indicates the
|
||||
* encoding and representation. We're only interested in ASCII
|
||||
* encoded strings whose representation is one of:
|
||||
* encoding and representation. We're only interested in strings
|
||||
* whose representation is one of:
|
||||
*
|
||||
* SeqString stored directly as a char array inside the object
|
||||
* SeqOneByteString stored directly as a char array inside the object
|
||||
*
|
||||
* ConsString pointer to two strings that should be concatenated
|
||||
* SeqTwoByteString stored as a UTF-16 char array inside the object
|
||||
*
|
||||
* ExternalString pointer to a char* outside the V8 heap
|
||||
* ConsString pointer to two strings that should be concatenated
|
||||
*
|
||||
* ExternalString pointer to a char* outside the V8 heap
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -141,27 +149,79 @@
|
|||
this->map = V8_MAP_PTR(COPYIN_PTR(str + V8_OFF_HEAPOBJ_MAP)); \
|
||||
attrs = COPYIN_UINT8(this->map + V8_OFF_MAP_ATTRS);
|
||||
|
||||
#define APPEND_SEQSTR(str, len, attrs) \
|
||||
APPEND_SEQONEBYTESTR(str, len, attrs) \
|
||||
APPEND_SEQTWOBYTESTR(str, len, attrs)
|
||||
|
||||
/*
|
||||
* Print out the given SeqString, or do nothing if the string is not an ASCII
|
||||
* SeqString.
|
||||
* Print out the given SeqOneByteString, or do nothing if the string is not an ASCII
|
||||
* SeqOneByteString.
|
||||
*/
|
||||
#define APPEND_SEQSTR(str, len, attrs) \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && ASCII_SEQSTR(attrs)/ \
|
||||
{ \
|
||||
#define APPEND_SEQONEBYTESTR(str, len, attrs) \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && ASCII_SEQSTR(attrs)/ \
|
||||
{ \
|
||||
copyinto(str + V8_OFF_STR_CHARS, len, this->buf + this->off); \
|
||||
this->off += len; \
|
||||
}
|
||||
|
||||
/*
|
||||
* LOOP_ITER: macro to paste "block" while "ivar" is less than "dynmax" and
|
||||
* "statmax". The subsequent LOOP_{4,8} macros facilitate pasting the same
|
||||
* thing 4 and 8 times, respectively. Like much of the rest of the code in this
|
||||
* file, this is regrettably necessary given the constraints under which we're
|
||||
* expected to run.
|
||||
*/
|
||||
#define LOOP_ITER(ivar, dynmax, statmax, block) \
|
||||
((ivar) < (dynmax)) && ((ivar) < (statmax)) && (block); (ivar)++;
|
||||
|
||||
#define LOOP_4(block) \
|
||||
block \
|
||||
block \
|
||||
block \
|
||||
block \
|
||||
|
||||
#define LOOP_8(block) \
|
||||
LOOP_4(block) \
|
||||
LOOP_4(block)
|
||||
|
||||
/*
|
||||
* Print out the given SeqTwoByteString, or do nothing if the string is not an ASCII
|
||||
* SeqTwoByteString. NOTE: if you bump MAX_TWOBYTESTR_CHARS, you'll also need
|
||||
* to modify the LOOP_* macro calls below to match.
|
||||
*/
|
||||
#define MAX_TWOBYTESTR_CHARS 128
|
||||
#define MAX_TWOBYTESTR_BYTES (2 * MAX_TWOBYTESTR_CHARS)
|
||||
#define TO_ASCII(c) ((c) < 128 ? (c) : '?')
|
||||
|
||||
#define APPEND_SEQTWOBYTESTR(str, len, attrs) \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && TWOBYTE_SEQSTR(attrs)/ \
|
||||
{ \
|
||||
this->i = 0; \
|
||||
this->stbuf = (uint16_t *)alloca(MAX_TWOBYTESTR_BYTES + 2); \
|
||||
copyinto(str + V8_OFF_TWOBYTESTR_CHARS, \
|
||||
MAX_TWOBYTESTR_BYTES, this->stbuf); \
|
||||
this->stbuf[MAX_TWOBYTESTR_BYTES - 1] = '\0'; \
|
||||
this->stbuf[MAX_TWOBYTESTR_BYTES] = '\0'; \
|
||||
\
|
||||
LOOP_8(LOOP_8(LOOP_4(LOOP_ITER(this->i, len, \
|
||||
MAX_TWOBYTESTR_CHARS, \
|
||||
APPEND_CHR(TO_ASCII(this->stbuf[this->i])))))) \
|
||||
\
|
||||
this->i = 0; \
|
||||
this->stbuf = 0; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out the given Node.js ExternalString, or do nothing if the string is
|
||||
* not an ASCII ExternalString.
|
||||
*/
|
||||
#define APPEND_NODESTR(str, len, attrs) \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && ASCII_EXTSTR(attrs)/ \
|
||||
{ \
|
||||
this->resource = COPYIN_PTR(str + V8_OFF_EXTSTR_RSRC); \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && ASCII_EXTSTR(attrs)/ \
|
||||
{ \
|
||||
this->resource = COPYIN_PTR(str + V8_OFF_EXTSTR_RSRC); \
|
||||
this->dataptr = COPYIN_PTR(this->resource + NODE_OFF_EXTSTR_DATA); \
|
||||
copyinto(this->dataptr, len, this->buf + this->off); \
|
||||
this->off += len; \
|
||||
|
|
@ -226,7 +286,7 @@
|
|||
*/
|
||||
#define EXPAND_STR(str, len, attrs, s1s, s1l, s1a, s2s, s2l, s2a) \
|
||||
dtrace:helper:ustack: \
|
||||
/!this->done && len > 0 && ASCII_CONSSTR(attrs)/ \
|
||||
/!this->done && len > 0 && IS_CONSSTR(attrs)/ \
|
||||
{ \
|
||||
len = 0; \
|
||||
\
|
||||
|
|
@ -316,6 +376,7 @@ dtrace:helper:ustack:
|
|||
this->funcnamelen = 0;
|
||||
this->funcnameattrs = 0;
|
||||
this->script = (off_t) 0;
|
||||
this->scriptattrs = 0;
|
||||
this->scriptnamestr = (off_t) 0;
|
||||
this->scriptnamelen = 0;
|
||||
this->scriptnameattrs = 0;
|
||||
|
|
@ -409,6 +470,16 @@ dtrace:helper:ustack:
|
|||
stringof(this->buf);
|
||||
}
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done && IS_SMI(this->marker) &&
|
||||
SMI_VALUE(this->marker) == V8_FT_STUB/
|
||||
{
|
||||
this->done = 1;
|
||||
APPEND_CHR8('<','<',' ','s','t','u','b',' ');
|
||||
APPEND_CHR4('>','>','\0','\0');
|
||||
stringof(this->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check for internal frames that we can only identify by seeing that
|
||||
* there's a Code object where there would be a JSFunction object for a
|
||||
|
|
@ -477,24 +548,38 @@ dtrace:helper:ustack:
|
|||
APPEND_V8STR(this->funcnamestr, this->funcnamelen, this->funcnameattrs)
|
||||
|
||||
/*
|
||||
* Now look for the name of the script where the function was defined.
|
||||
* Now look for the name of the script where the function was defined. The
|
||||
* "script" itself may be undefined for special functions like "RegExp".
|
||||
*/
|
||||
dtrace:helper:ustack:
|
||||
/!this->done/
|
||||
{
|
||||
this->script = COPYIN_PTR(this->shared + V8_OFF_SHARED_SCRIPT);
|
||||
this->scriptnamestr = COPYIN_PTR(this->script + V8_OFF_SCRIPT_NAME);
|
||||
LOAD_STRFIELDS(this->scriptnamestr, this->scriptnamelen,
|
||||
this->scriptnameattrs);
|
||||
|
||||
APPEND_CHR4(' ','a','t',' ');
|
||||
this->map = V8_MAP_PTR(COPYIN_PTR(this->script + V8_OFF_HEAPOBJ_MAP));
|
||||
this->scriptattrs = COPYIN_UINT8(this->map + V8_OFF_MAP_ATTRS);
|
||||
}
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done && this->scriptnamelen == 0/
|
||||
/!this->done && !V8_TYPE_SCRIPT(this->scriptattrs)/
|
||||
{
|
||||
APPEND_CHR8('<','u','n','k','n','o','w','n');
|
||||
APPEND_CHR('>');
|
||||
APPEND_CHR('\0');
|
||||
this->done = 1;
|
||||
stringof(this->buf);
|
||||
}
|
||||
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done/
|
||||
{
|
||||
this->scriptnamestr = COPYIN_PTR(this->script + V8_OFF_SCRIPT_NAME);
|
||||
LOAD_STRFIELDS(this->scriptnamestr, this->scriptnamelen,
|
||||
this->scriptnameattrs);
|
||||
}
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done && this->scriptnamelen != 0/
|
||||
{
|
||||
APPEND_CHR4(' ','a','t',' ');
|
||||
}
|
||||
|
||||
APPEND_V8STR(this->scriptnamestr, this->scriptnamelen, this->scriptnameattrs)
|
||||
|
|
@ -511,6 +596,14 @@ dtrace:helper:ustack:
|
|||
this->le_attrs = COPYIN_UINT8(this->map + V8_OFF_MAP_ATTRS);
|
||||
}
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done && this->le_attrs != V8_IT_FIXEDARRAY && this->position == 0/
|
||||
{
|
||||
APPEND_CHR('\0');
|
||||
this->done = 1;
|
||||
stringof(this->buf);
|
||||
}
|
||||
|
||||
dtrace:helper:ustack:
|
||||
/!this->done && this->le_attrs != V8_IT_FIXEDARRAY/
|
||||
{
|
||||
|
|
@ -519,10 +612,9 @@ dtrace:helper:ustack:
|
|||
* undefined because V8 has not had to compute it yet. In this case we
|
||||
* just show the raw position and call it a day.
|
||||
*/
|
||||
APPEND_CHR8(' ','p','o','s','i','t','i','o');
|
||||
APPEND_CHR('n');
|
||||
APPEND_CHR4(' ','p','o','s');
|
||||
APPEND_CHR(' ');
|
||||
APPEND_NUM(this->position);
|
||||
APPEND_NUM(SMI_VALUE(this->position));
|
||||
APPEND_CHR('\0');
|
||||
this->done = 1;
|
||||
stringof(this->buf);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user