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