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