V8

This is a collection of basic concepts, commands and everything else I could find on V8 and found noteworthy as of January 2024 (V8 commit: 978989e7ec945824b293a8093238ceedb2b06d17).

Tutorials

Basic Concepts

Components

d8 Options

d8 Debug

d8 Analysis

This section contains examples of how to analyse and navigate the representations of V8 objects in memory using a debugger. We will use lldb and so every example starts d8 with the command:

$ lldb -- ./d8 --allow-natives-syntax

String

The first entry points to a map that defines the string type INTERNALIZED_ONE_BYTE_STRING_TYPE. Note, the length of the string is not in SMI format (i.e., it is just a regular integer).

d8> let a = "Hello World!"
d8> %DebugPrint(a)
DebugPrint: 0x296f000da7ad: [String] in OldSpace: #Hello World!
0x296f000003d5: [Map] in ReadOnlySpace
 - map: 0x296f000004c5 <MetaMap (0x296f0000007d <null>)>
 - type: INTERNALIZED_ONE_BYTE_STRING_TYPE
 
Ctrl^C
(lldb) x/wx 0x296f000da7ad-1+8   /* third entry */
0x296f000da7b4: 0x0000000c       /* = a.length */

(lldb) x/s 0x296f000da7ad-1+12   /* fourth entry */
0x296f000da7b8: "Hello World!"   /* = raw string */

JSPrimitiveWrapper (String)

This is a regular JSObject. The first entry point to a map that defines the string type as FAST_STRING_WRAPPER_ELEMENTS. The fourth entry (the first in-line property of the JSObject) is used to store the value which is a pointer to a String object.

d8> let a = new String("Hello World!")
d8> %DebugPrint(a)
DebugPrint: 0x3cd7001ca111: [JSPrimitiveWrapper]
- map: 0x3cd7000c8c31 <Map[16](FAST_STRING_WRAPPER_ELEMENTS)> [FastProperties]
- prototype: 0x3cd7000c8f0d <Object map = 0x3cd7000c8c59 value = 0x3cd700000099 <String[0]: #>>
- elements: 0x3cd7000006cd <FixedArray[0]> [FAST_STRING_WRAPPER_ELEMENTS]
- value: 0x3cd7000da7ad <String[11]: #Hello World>
...

Ctrl^C
(lldb) x/wx 0x3cd7000da7ad-1+8   /* third entry */
0x3cd7000da7b4: 0x0000000b       /* = a.length */

(lldb) x/s 0x3cd7000da7ad-1+12   /* fourth entry */
0x3cd7000da7b8: "Hello World"    /* = raw string */

JSArray

d8> let a = [1,2,3,4,5,6,7,8,9,0]
d8> %DebugPrint(a)
DebugPrint: 0x173d001ca10d: [JSArray]
- map: 0x173d000ce6c1 <Map[16](PACKED_SMI_ELEMENTS)> [FastProperties]
- prototype: 0x173d000ce935 <JSArray[0]>
- elements: 0x173d000da811 <FixedArray[10]> [PACKED_SMI_ELEMENTS (COW)]
- length: 10
- properties: 0x173d000006cd <FixedArray[0]>
- All own properties (excluding elements): {
0x173d00000d41: [String] in ReadOnlySpace: #length: 0x173d0030ed89 <AccessorInfo name= 0x173d00000d41 <String[6]: #length>, data= 0x173d00000061 <undefined>> (const accessor descriptor), location: descriptor
}
- elements: 0x173d000da811 <FixedArray[10]> {
0: 1
1: 2
2: 3
3: 4
4: 5
5: 6
6: 7
7: 8
8: 9
9: 0
}
...

Ctrl^C
(lldb) x/wx 0x173d001ca10d-1+8   /* third entry */
0x173d001ca114: 0x000da811       /* = pointer to elements */
(lldb) x/wx 0x173d001ca10d-1+12  /* fourth entry */
0x173d001ca118: 0x00000014       /* = (0x14 >> 1) == a.length */

CVEs

CTFs

Unreviewed

Misc