1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#include "gtest/gtest.h"
#include "node.h"
#include "node_internals.h"
#include "node_test_fixture.h"
#include "req_wrap-inl.h"
#include "tracing/agent.h"
#include "v8.h"
#define NODE_OFF_EXTSTR_DATA sizeof(void*)
extern "C" {
extern uintptr_t
nodedbg_offset_HandleWrap__handle_wrap_queue___ListNode_HandleWrap;
extern uintptr_t
nodedbg_offset_Environment__handle_wrap_queue___Environment_HandleWrapQueue;
extern int debug_symbols_generated;
extern int nodedbg_const_ContextEmbedderIndex__kEnvironment__int;
extern int nodedbg_const_BaseObject__kInternalFieldCount__int;
extern uintptr_t
nodedbg_offset_Environment_HandleWrapQueue__head___ListNode_HandleWrap;
extern uintptr_t
nodedbg_offset_Environment__req_wrap_queue___Environment_ReqWrapQueue;
extern uintptr_t nodedbg_offset_ExternalString__data__uintptr_t;
extern uintptr_t nodedbg_offset_ListNode_ReqWrap__prev___uintptr_t;
extern uintptr_t nodedbg_offset_ListNode_ReqWrap__next___uintptr_t;
extern uintptr_t nodedbg_offset_ReqWrap__req_wrap_queue___ListNode_ReqWrapQueue;
extern uintptr_t nodedbg_offset_ListNode_HandleWrap__prev___uintptr_t;
extern uintptr_t nodedbg_offset_ListNode_HandleWrap__next___uintptr_t;
extern uintptr_t
nodedbg_offset_Environment_ReqWrapQueue__head___ListNode_ReqWrapQueue;
extern uintptr_t
nodedbg_offset_BaseObject__persistent_handle___v8_Persistent_v8_Object;
}
class DebugSymbolsTest : public EnvironmentTestFixture {};
class TestHandleWrap : public node::HandleWrap {
public:
SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(TestHandleWrap)
SET_SELF_SIZE(TestHandleWrap)
TestHandleWrap(node::Environment* env,
v8::Local<v8::Object> object,
uv_tcp_t* handle)
: node::HandleWrap(env,
object,
reinterpret_cast<uv_handle_t*>(handle),
node::AsyncWrap::PROVIDER_TCPWRAP) {}
};
class TestReqWrap : public node::ReqWrap<uv_req_t> {
public:
SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(TestReqWrap)
SET_SELF_SIZE(TestReqWrap)
TestReqWrap(node::Environment* env, v8::Local<v8::Object> object)
: node::ReqWrap<uv_req_t>(env,
object,
node::AsyncWrap::PROVIDER_FSREQCALLBACK) {}
};
TEST_F(DebugSymbolsTest, ContextEmbedderEnvironmentIndex) {
int kEnvironmentIndex = node::ContextEmbedderIndex::kEnvironment;
EXPECT_EQ(nodedbg_const_ContextEmbedderIndex__kEnvironment__int,
kEnvironmentIndex);
}
TEST_F(DebugSymbolsTest, BaseObjectkInternalFieldCount) {
int kInternalFieldCount = node::BaseObject::kInternalFieldCount;
EXPECT_EQ(nodedbg_const_BaseObject__kInternalFieldCount__int,
kInternalFieldCount);
}
TEST_F(DebugSymbolsTest, ExternalStringDataOffset) {
EXPECT_EQ(nodedbg_offset_ExternalString__data__uintptr_t,
NODE_OFF_EXTSTR_DATA);
}
class DummyBaseObject : public node::BaseObject {
public:
DummyBaseObject(node::Environment* env, v8::Local<v8::Object> obj) :
BaseObject(env, obj) {}
SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(DummyBaseObject)
SET_SELF_SIZE(DummyBaseObject)
};
TEST_F(DebugSymbolsTest, BaseObjectPersistentHandle) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env{handle_scope, argv};
v8::Local<v8::ObjectTemplate> obj_templ = v8::ObjectTemplate::New(isolate_);
obj_templ->SetInternalFieldCount(
nodedbg_const_BaseObject__kInternalFieldCount__int);
v8::Local<v8::Object> object =
obj_templ->NewInstance(env.context()).ToLocalChecked();
node::BaseObjectPtr<DummyBaseObject> obj =
node::MakeDetachedBaseObject<DummyBaseObject>(*env, object);
auto expected = reinterpret_cast<uintptr_t>(&obj->persistent());
auto calculated = reinterpret_cast<uintptr_t>(obj.get()) +
nodedbg_offset_BaseObject__persistent_handle___v8_Persistent_v8_Object;
EXPECT_EQ(expected, calculated);
}
TEST_F(DebugSymbolsTest, EnvironmentHandleWrapQueue) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env{handle_scope, argv};
auto expected = reinterpret_cast<uintptr_t>((*env)->handle_wrap_queue());
auto calculated = reinterpret_cast<uintptr_t>(*env) +
nodedbg_offset_Environment__handle_wrap_queue___Environment_HandleWrapQueue; // NOLINT(whitespace/line_length)
EXPECT_EQ(expected, calculated);
}
TEST_F(DebugSymbolsTest, EnvironmentReqWrapQueue) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env{handle_scope, argv};
auto expected = reinterpret_cast<uintptr_t>((*env)->req_wrap_queue());
auto calculated = reinterpret_cast<uintptr_t>(*env) +
nodedbg_offset_Environment__req_wrap_queue___Environment_ReqWrapQueue;
EXPECT_EQ(expected, calculated);
}
TEST_F(DebugSymbolsTest, HandleWrapList) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env{handle_scope, argv};
auto queue = reinterpret_cast<uintptr_t>((*env)->handle_wrap_queue());
auto head = queue +
nodedbg_offset_Environment_HandleWrapQueue__head___ListNode_HandleWrap;
auto tail = head + nodedbg_offset_ListNode_HandleWrap__prev___uintptr_t;
tail = *reinterpret_cast<uintptr_t*>(tail);
uv_tcp_t handle;
auto obj_template = v8::FunctionTemplate::New(isolate_);
obj_template->InstanceTemplate()->SetInternalFieldCount(
nodedbg_const_BaseObject__kInternalFieldCount__int);
v8::Local<v8::Object> object = obj_template->GetFunction(env.context())
.ToLocalChecked()
->NewInstance(env.context())
.ToLocalChecked();
TestHandleWrap obj(*env, object, &handle);
auto last = tail + nodedbg_offset_ListNode_HandleWrap__next___uintptr_t;
last = *reinterpret_cast<uintptr_t*>(last);
auto expected = reinterpret_cast<uintptr_t>(&obj);
auto calculated =
last - nodedbg_offset_HandleWrap__handle_wrap_queue___ListNode_HandleWrap;
EXPECT_EQ(expected, calculated);
obj.persistent().Reset(); // ~HandleWrap() expects an empty handle.
}
TEST_F(DebugSymbolsTest, ReqWrapList) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env{handle_scope, argv};
auto queue = reinterpret_cast<uintptr_t>((*env)->req_wrap_queue());
auto head =
queue +
nodedbg_offset_Environment_ReqWrapQueue__head___ListNode_ReqWrapQueue;
auto tail = head + nodedbg_offset_ListNode_ReqWrap__prev___uintptr_t;
tail = *reinterpret_cast<uintptr_t*>(tail);
auto obj_template = v8::FunctionTemplate::New(isolate_);
obj_template->InstanceTemplate()->SetInternalFieldCount(
nodedbg_const_BaseObject__kInternalFieldCount__int);
v8::Local<v8::Object> object = obj_template->GetFunction(env.context())
.ToLocalChecked()
->NewInstance(env.context())
.ToLocalChecked();
TestReqWrap obj(*env, object);
// NOTE (mmarchini): Workaround to fix failing tests on ARM64 machines with
// older GCC. Should be removed once we upgrade the GCC version used on our
// ARM64 CI machinies.
for (auto it : *(*env)->req_wrap_queue()) (void) ⁢
volatile uintptr_t last =
tail + nodedbg_offset_ListNode_ReqWrap__next___uintptr_t;
last = *reinterpret_cast<uintptr_t*>(last);
auto expected = reinterpret_cast<uintptr_t>(&obj);
auto calculated =
last - nodedbg_offset_ReqWrap__req_wrap_queue___ListNode_ReqWrapQueue;
EXPECT_EQ(expected, calculated);
obj.Dispatched();
}
|