forked from nodejs/llnode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: add commands to inspect the workqueue
Added two new commands (getactivehandles and getactiverequests) which prints all pending handles and requests (same return given by process._getActiveHandles() and process._getActiveRequests()). Those changes were built upon the symbols added on nodejs/node#14901, which means it's currently not working with node's latest build. Fixes: nodejs#100 Ref: nodejs/node#14901
- Loading branch information
Matheus Marchini
authored and
Matheus Marchini
committed
Mar 13, 2018
1 parent
995d0bb
commit dceed10
Showing
16 changed files
with
822 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include "src/constants.h" | ||
#include "src/llv8.h" | ||
|
||
namespace llnode { | ||
using v8::Error; | ||
using v8::constants::IsDebugMode; | ||
using v8::constants::LookupConstant; | ||
namespace constants { | ||
|
||
void ConstantsWrapper::Assign(SBTarget target) { | ||
loaded_ = false; | ||
target_ = target; | ||
} | ||
|
||
int64_t ConstantsWrapper::LoadRawConstant(const char* name, int64_t def) { | ||
Error err; | ||
int64_t v = LookupConstant(target_, name, def, err); | ||
if (err.Fail() && IsDebugMode()) fprintf(stderr, "Failed to load %s\n", name); | ||
|
||
return v; | ||
} | ||
|
||
|
||
int64_t ConstantsWrapper::LoadConstant(const char* name, int64_t def) { | ||
Error err; | ||
int64_t v = | ||
LookupConstant(target_, (kConstantPrefix() + name).c_str(), def, err); | ||
if (err.Fail() && IsDebugMode()) fprintf(stderr, "Failed to load %s\n", name); | ||
|
||
return v; | ||
} | ||
|
||
|
||
int64_t ConstantsWrapper::LoadConstant(const char* name, const char* fallback, | ||
int64_t def) { | ||
Error err; | ||
int64_t v = | ||
LookupConstant(target_, (kConstantPrefix() + name).c_str(), def, err); | ||
if (err.Fail()) | ||
v = LookupConstant(target_, (kConstantPrefix() + fallback).c_str(), def, | ||
err); | ||
if (err.Fail() && IsDebugMode()) fprintf(stderr, "Failed to load %s\n", name); | ||
|
||
return v; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef SRC_CONSTANTS_H_ | ||
#define SRC_CONSTANTS_H_ | ||
|
||
#include <lldb/API/LLDB.h> | ||
#include <string> | ||
using lldb::SBTarget; | ||
|
||
namespace llnode { | ||
namespace constants { | ||
|
||
class ConstantsWrapper { | ||
public: | ||
ConstantsWrapper() : loaded_(false) {} | ||
|
||
inline bool is_loaded() const { return loaded_; } | ||
|
||
void Assign(lldb::SBTarget target); | ||
|
||
inline virtual std::string kConstantPrefix() { return ""; }; | ||
|
||
protected: | ||
int64_t LoadRawConstant(const char* name, int64_t def = -1); | ||
int64_t LoadConstant(const char* name, int64_t def = -1); | ||
int64_t LoadConstant(const char* name, const char* fallback, | ||
int64_t def = -1); | ||
|
||
lldb::SBTarget target_; | ||
bool loaded_; | ||
}; | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include <lldb/API/LLDB.h> | ||
|
||
#include "llnode-constants.h" | ||
#include "llv8-constants.h" | ||
#include "llv8-inl.h" | ||
#include "llv8.h" | ||
|
||
using lldb::SBProcess; | ||
using lldb::SBThread; | ||
using lldb::SBError; | ||
using lldb::SBFrame; | ||
using lldb::SBStream; | ||
|
||
namespace llnode { | ||
using v8::Error; | ||
using v8::constants::LookupConstant; | ||
namespace node { | ||
namespace constants { | ||
v8::LLV8 llv8; | ||
|
||
void Environment::Load() { | ||
kIsolate = LoadRawConstant("node::node_isolate"); | ||
kReqWrapQueueOffset = LoadConstant("class__Environment__reqWrapQueue", 1256); | ||
kHandleWrapQueueOffset = | ||
LoadConstant("class__Environment__handleWrapQueue", 1240); | ||
kEnvContextEmbedderDataIndex = | ||
LoadConstant("environment_context_idx_embedder_data", 32); | ||
kCurrentEnvironment = LoadCurrentEnvironment(); | ||
} | ||
|
||
addr_t Environment::LoadCurrentEnvironment() { | ||
addr_t currentEnvironment = DefaultLoadCurrentEnvironment(); | ||
if (currentEnvironment == -1) { | ||
currentEnvironment = FallbackLoadCurrentEnvironment(); | ||
} | ||
|
||
return currentEnvironment; | ||
} | ||
|
||
addr_t Environment::DefaultLoadCurrentEnvironment() { | ||
llv8.Load(target_); | ||
|
||
SBProcess process = target_.GetProcess(); | ||
SBError sberr; | ||
uint64_t env = -1; | ||
uint64_t isolate_thread = 0; | ||
uint64_t thread_context_ptr = 0; | ||
uint64_t thread_context = 0; | ||
v8::Error err; | ||
|
||
if (!(llv8.isolate()->kThreadLocalTopOffset != -1 && | ||
llv8.thread_local_top()->kContextOffset != -1)) { | ||
return env; | ||
} | ||
|
||
isolate_thread = kIsolate + llv8.isolate()->kThreadLocalTopOffset; | ||
|
||
thread_context_ptr = isolate_thread + llv8.thread_local_top()->kContextOffset; | ||
thread_context = process.ReadPointerFromMemory(thread_context_ptr, sberr); | ||
if (sberr.Fail()) { | ||
return -1; | ||
} | ||
v8::Context ctx(&llv8, thread_context); | ||
v8::Value native = ctx.Native(err); | ||
if (err.Fail()) { | ||
return -1; | ||
} | ||
env = CurrentEnvironmentFromContext(native); | ||
return env; | ||
} | ||
|
||
addr_t Environment::CurrentEnvironmentFromContext(v8::Value context) { | ||
llv8.Load(target_); | ||
v8::Error err; | ||
|
||
v8::FixedArray contextArray = v8::FixedArray(context); | ||
v8::FixedArray embed = | ||
contextArray.Get<v8::FixedArray>(llv8.context()->kEmbedderDataIndex, err); | ||
if (err.Fail()) { | ||
return -1; | ||
} | ||
v8::Smi encodedEnv = embed.Get<v8::Smi>(kEnvContextEmbedderDataIndex, err); | ||
if (err.Fail()) { | ||
return -1; | ||
} else { | ||
return encodedEnv.raw(); | ||
} | ||
} | ||
|
||
addr_t Environment::FallbackLoadCurrentEnvironment() { | ||
addr_t env = -1; | ||
SBProcess process = target_.GetProcess(); | ||
SBThread thread = process.GetSelectedThread(); | ||
if (!thread.IsValid()) { | ||
return -1; | ||
} | ||
|
||
llv8.Load(target_); | ||
|
||
SBStream desc; | ||
if (!thread.GetDescription(desc)) { | ||
return -1; | ||
} | ||
SBFrame selected_frame = thread.GetSelectedFrame(); | ||
|
||
uint32_t num_frames = thread.GetNumFrames(); | ||
for (uint32_t i = 0; i < num_frames; i++) { | ||
SBFrame frame = thread.GetFrameAtIndex(i); | ||
|
||
if (!frame.GetSymbol().IsValid()) { | ||
v8::Error err; | ||
v8::JSFrame v8_frame(&llv8, static_cast<int64_t>(frame.GetFP())); | ||
v8::JSFunction v8_function = v8_frame.GetFunction(err); | ||
if (err.Fail()) { | ||
continue; | ||
} | ||
v8::Value val; | ||
val = v8_function.GetContext(err); | ||
if (err.Fail()) { | ||
continue; | ||
} | ||
bool found = false; | ||
while (!found) { | ||
v8::Context context(val); | ||
v8::Value native = context.Native(err); | ||
if (err.Success()) { | ||
if (native.raw() == context.raw()) { | ||
found = true; | ||
env = CurrentEnvironmentFromContext(native); | ||
break; | ||
} | ||
} | ||
|
||
val = context.Previous(err); | ||
if (err.Fail()) { | ||
break; | ||
} | ||
} | ||
if (found) { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return env; | ||
} | ||
|
||
|
||
void ReqWrapQueue::Load() { | ||
kHeadOffset = LoadConstant("class__ReqWrapQueue__headOffset", (int64_t)0); | ||
kNextOffset = LoadConstant("class__ReqWrapQueue__nextOffset", (int64_t)8); | ||
} | ||
|
||
void ReqWrap::Load() { | ||
kListNodeOffset = LoadConstant("class__ReqWrap__node", (int64_t)48); | ||
} | ||
|
||
void HandleWrapQueue::Load() { | ||
kHeadOffset = LoadConstant("class__HandleWrapQueue__headOffset", (int64_t)0); | ||
kNextOffset = LoadConstant("class__HandleWrapQueue__nextOffset", (int64_t)8); | ||
} | ||
|
||
void HandleWrap::Load() { | ||
kListNodeOffset = LoadConstant("class__HandleWrap__node", (int64_t)48); | ||
} | ||
|
||
void BaseObject::Load() { | ||
kPersistentHandleOffset = | ||
LoadConstant("class__BaseObject__persistent_handle", (int64_t)8); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#ifndef SRC_LLNODE_CONSTANTS_H_ | ||
#define SRC_LLNODE_CONSTANTS_H_ | ||
|
||
#include <lldb/API/LLDB.h> | ||
#include "src/constants.h" | ||
#include "src/llv8.h" | ||
|
||
using lldb::addr_t; | ||
|
||
namespace llnode { | ||
using constants::ConstantsWrapper; | ||
namespace node { | ||
namespace constants { | ||
#define MODULE_DEFAULT_METHODS(NAME) \ | ||
NAME() {} \ | ||
inline NAME* operator()() { \ | ||
if (loaded_) return this; \ | ||
loaded_ = true; \ | ||
Load(); \ | ||
return this; \ | ||
} | ||
|
||
|
||
class Module : public ConstantsWrapper { | ||
public: | ||
inline std::string kConstantPrefix() override { return "nodedbg_"; }; | ||
}; | ||
|
||
class Environment : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(Environment); | ||
|
||
int64_t kIsolate; | ||
int64_t kReqWrapQueueOffset; | ||
int64_t kHandleWrapQueueOffset; | ||
int64_t kEnvContextEmbedderDataIndex; | ||
addr_t kCurrentEnvironment; | ||
|
||
protected: | ||
void Load(); | ||
|
||
private: | ||
addr_t LoadCurrentEnvironment(); | ||
addr_t DefaultLoadCurrentEnvironment(); | ||
addr_t FallbackLoadCurrentEnvironment(); | ||
addr_t CurrentEnvironmentFromContext(v8::Value context); | ||
}; | ||
|
||
class ReqWrapQueue : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(ReqWrapQueue); | ||
|
||
int64_t kHeadOffset; | ||
int64_t kNextOffset; | ||
|
||
protected: | ||
void Load(); | ||
}; | ||
|
||
class ReqWrap : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(ReqWrap); | ||
|
||
int64_t kListNodeOffset; | ||
|
||
protected: | ||
void Load(); | ||
}; | ||
|
||
class HandleWrapQueue : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(HandleWrapQueue); | ||
|
||
int64_t kHeadOffset; | ||
int64_t kNextOffset; | ||
|
||
protected: | ||
void Load(); | ||
}; | ||
|
||
class HandleWrap : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(HandleWrap); | ||
|
||
int64_t kListNodeOffset; | ||
|
||
protected: | ||
void Load(); | ||
}; | ||
|
||
class BaseObject : public Module { | ||
public: | ||
MODULE_DEFAULT_METHODS(BaseObject); | ||
|
||
int64_t kPersistentHandleOffset; | ||
|
||
protected: | ||
void Load(); | ||
}; | ||
} | ||
} | ||
} | ||
|
||
#endif |
Oops, something went wrong.