From 9affb0e42cce5dd6965cf5c2e2e45ccbe5569d93 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Tue, 29 Aug 2017 17:21:33 -0300 Subject: [PATCH] src: refactor of workqueue related code All code related to the workqueue commands were refactored by assigning constants in a different file and by creating helper classes to access some node internal properties. Besides that, a new fallback method to determine the current environment was added. This method uses a heuristic approach to try to find the root context of the process. With this, those new commands will work most of the time even without the new symbols added to V8. --- llnode.gyp.json | 3 + src/constants.cc | 51 ++++++++++++ src/constants.h | 32 ++++++++ src/llnode-constants.cc | 169 ++++++++++++++++++++++++++++++++++++++++ src/llnode-constants.h | 104 +++++++++++++++++++++++++ src/llnode-module-inl.h | 42 ++++++++++ src/llnode-module.cc | 69 ++++++++++++++++ src/llnode-module.h | 125 +++++++++++++++++++++++++++++ src/llnode.cc | 131 ++++++------------------------- src/llv8-constants.cc | 15 +++- src/llv8-constants.h | 22 +++++- src/llv8-inl.h | 4 + src/llv8.cc | 2 + src/llv8.h | 8 +- 14 files changed, 666 insertions(+), 111 deletions(-) create mode 100644 src/constants.cc create mode 100644 src/constants.h create mode 100644 src/llnode-constants.cc create mode 100644 src/llnode-constants.h create mode 100644 src/llnode-module-inl.h create mode 100644 src/llnode-module.cc create mode 100644 src/llnode-module.h diff --git a/llnode.gyp.json b/llnode.gyp.json index ce6bd42d..423b45ce 100644 --- a/llnode.gyp.json +++ b/llnode.gyp.json @@ -16,7 +16,10 @@ ], "sources": [ + "src/constants.cc", "src/llnode.cc", + "src/llnode-module.cc", + "src/llnode-constants.cc", "src/llv8.cc", "src/llv8-constants.cc", "src/llscan.cc", diff --git a/src/constants.cc b/src/constants.cc new file mode 100644 index 00000000..067a51cd --- /dev/null +++ b/src/constants.cc @@ -0,0 +1,51 @@ +#include "src/constants.h" +// TODO(mmarchini): This file shouldn't import llv8-constants nor llv8, as the +// intention is to inherit llv8-constants.h from constants.h +#include +#include "src/llv8-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; +} +} +} diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 00000000..610728b5 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,32 @@ +#ifndef SRC_CONSTANTS_H_ +#define SRC_CONSTANTS_H_ + +#include +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 diff --git a/src/llnode-constants.cc b/src/llnode-constants.cc new file mode 100644 index 00000000..c8cefced --- /dev/null +++ b/src/llnode-constants.cc @@ -0,0 +1,169 @@ +#include + +#include + +#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)) { + // TODO warn user + 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); + v8::Context ctx(&llv8, thread_context); + v8::Value native = ctx.Native(err); + 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(llv8.context()->kEmbedderDataIndex, err); + v8::Smi encodedEnv = embed.Get(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; + } + + // Load V8 constants from postmortem data + 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(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); +} +} +} +} diff --git a/src/llnode-constants.h b/src/llnode-constants.h new file mode 100644 index 00000000..519e9757 --- /dev/null +++ b/src/llnode-constants.h @@ -0,0 +1,104 @@ +#ifndef SRC_LLNODE_CONSTANTS_H_ +#define SRC_LLNODE_CONSTANTS_H_ + +#include +#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 diff --git a/src/llnode-module-inl.h b/src/llnode-module-inl.h new file mode 100644 index 00000000..7b723d78 --- /dev/null +++ b/src/llnode-module-inl.h @@ -0,0 +1,42 @@ +#include "llnode-module.h" + +namespace llnode { +namespace node { + +template +T Queue::Iterator::operator*() const { + return T::FromListNode(node_, current_); +} + +template +const typename Queue::Iterator Queue::Iterator::operator++() { + lldb::SBError sberr; + + addr_t current = current_ + constants_->kNextOffset; + current = node_->process().ReadPointerFromMemory(current, sberr); + current_ = current; + return Iterator(node_, current, constants_); +} + +template +bool Queue::Iterator::operator!=(const Iterator& that) const { + return current_ != that.current_; +} + +template +typename Queue::Iterator Queue::begin() const { + lldb::SBError sberr; + addr_t currentNode = raw_ + constants_->kHeadOffset; + + currentNode = currentNode + constants_->kNextOffset; + currentNode = node_->process().ReadPointerFromMemory(currentNode, sberr); + + return Iterator(node_, currentNode, constants_); +} + +template +typename Queue::Iterator Queue::end() const { + return Iterator(node_, raw_ + constants_->kHeadOffset, constants_); +} +} +} diff --git a/src/llnode-module.cc b/src/llnode-module.cc new file mode 100644 index 00000000..2c10626e --- /dev/null +++ b/src/llnode-module.cc @@ -0,0 +1,69 @@ +#include "llnode-module.h" + +namespace llnode { +namespace node { + +addr_t BaseObject::persistent_addr() { + lldb::SBError sberr; + + addr_t persistentHandlePtr = + raw_ + node_->base_object()->kPersistentHandleOffset; + addr_t persistentHandle = + node_->process().ReadPointerFromMemory(persistentHandlePtr, sberr); + return persistentHandle; +} + +addr_t BaseObject::v8_object_addr() { + lldb::SBError sberr; + + addr_t persistentHandle = persistent_addr(); + addr_t obj = node_->process().ReadPointerFromMemory(persistentHandle, sberr); + return obj; +} + +HandleWrap HandleWrap::FromListNode(LLNode *node, addr_t list_node_addr) { + return HandleWrap(node, + list_node_addr - node->handle_wrap()->kListNodeOffset); +} + +ReqWrap ReqWrap::FromListNode(LLNode *node, addr_t list_node_addr) { + return ReqWrap(node, list_node_addr - node->req_wrap()->kListNodeOffset); +} + +Environment Environment::GetCurrent(LLNode *node) { + // TODO (mmarchini): maybe throw some warning here when env is not valid + addr_t envAddr = node->env()->kCurrentEnvironment; + + return Environment(node, envAddr); +} + +Queue Environment::handle_wrap_queue() + const { + return Queue( + node_, raw_ + node_->env()->kHandleWrapQueueOffset, + node_->handle_wrap_queue()); +} + +Queue Environment::req_wrap_queue() const { + return Queue( + node_, raw_ + node_->env()->kReqWrapQueueOffset, node_->req_wrap_queue()); +} + +void LLNode::Load(SBTarget target) { + // Reload process anyway + process_ = target.GetProcess(); + + // No need to reload + if (target_ == target) return; + + target_ = target; + + env.Assign(target); + req_wrap_queue.Assign(target); + req_wrap.Assign(target); + handle_wrap_queue.Assign(target); + handle_wrap.Assign(target); + base_object.Assign(target); +} +} +} diff --git a/src/llnode-module.h b/src/llnode-module.h new file mode 100644 index 00000000..20928b27 --- /dev/null +++ b/src/llnode-module.h @@ -0,0 +1,125 @@ +#ifndef SRC_LLNODE_MODULE_H_ +#define SRC_LLNODE_MODULE_H_ + +#include +#include + +#include "llnode-constants.h" + +namespace llnode { +namespace node { + +class LLNode; +class HandleWrap; +class ReqWrap; +template +class Queue; + +// TODO (mmarchini): give a better name +class BaseNode { + public: + BaseNode(LLNode *node) : node_(node){}; + + protected: + LLNode *node_; +}; + +class Environment : public BaseNode { + public: + Environment(LLNode *node, addr_t raw) : BaseNode(node), raw_(raw){}; + inline addr_t raw() { return raw_; }; + + static Environment GetCurrent(LLNode *node); + + Queue handle_wrap_queue() const; + Queue req_wrap_queue() const; + + private: + addr_t raw_; +}; + +class BaseObject : public BaseNode { + public: + BaseObject(LLNode *node, addr_t raw) : BaseNode(node), raw_(raw){}; + + addr_t persistent_addr(); + + addr_t v8_object_addr(); + + + private: + addr_t raw_; +}; + +class AsyncWrap : public BaseObject { + public: + // static std::list *GetEnvQueue(Environment *env); + AsyncWrap(LLNode *node, addr_t raw) : BaseObject(node, raw){}; +}; + +class HandleWrap : public AsyncWrap { + public: + HandleWrap(LLNode *node, addr_t raw) : AsyncWrap(node, raw){}; + + static HandleWrap FromListNode(LLNode *node, addr_t list_node_addr); +}; + +class ReqWrap : public AsyncWrap { + public: + ReqWrap(LLNode *node, addr_t raw) : AsyncWrap(node, raw){}; + + static ReqWrap FromListNode(LLNode *node, addr_t list_node_addr); +}; + +class LLNode { + public: + LLNode() : target_(lldb::SBTarget()) {} + + inline lldb::SBProcess process() { return process_; }; + + void Load(lldb::SBTarget target); + + constants::Environment env; + constants::ReqWrapQueue req_wrap_queue; + constants::ReqWrap req_wrap; + constants::HandleWrapQueue handle_wrap_queue; + constants::HandleWrap handle_wrap; + constants::BaseObject base_object; + + private: + lldb::SBTarget target_; + lldb::SBProcess process_; +}; + +template +class Queue : public BaseNode { + class Iterator : public BaseNode { + public: + inline T operator*() const; + inline const Iterator operator++(); + inline bool operator!=(const Iterator &that) const; + + + inline Iterator(LLNode *node, addr_t current, C *constants) + : BaseNode(node), current_(current), constants_(constants){}; + + public: + addr_t current_; + C *constants_; + }; + + public: + inline Queue(LLNode *node, addr_t raw, C *constants) + : BaseNode(node), raw_(raw), constants_(constants){}; + + inline Iterator begin() const; + inline Iterator end() const; + + private: + addr_t raw_; + C *constants_; +}; +} +} + +#endif diff --git a/src/llnode.cc b/src/llnode.cc index 11674629..182b077c 100644 --- a/src/llnode.cc +++ b/src/llnode.cc @@ -9,9 +9,12 @@ #include +#include "src/llnode-module-inl.h" +#include "src/llnode-module.h" #include "src/llnode.h" #include "src/llscan.h" #include "src/llv8-constants.h" +#include "src/llv8-inl.h" #include "src/llv8.h" namespace llnode { @@ -37,6 +40,7 @@ using lldb::addr_t; using v8::constants::LookupConstant; v8::LLV8 llv8; +node::LLNode nodeMod; char** CommandBase::ParseInspectOptions(char** cmd, v8::Value::InspectOptions* options) { @@ -319,79 +323,35 @@ bool GetActiveHandlesCmd::DoExecute(SBDebugger d, char** cmd, inspect_options.detailed = true; llv8.Load(target); + nodeMod.Load(target); - int size = 8; - int64_t envPtr = 0; - uint64_t env = 0; - int64_t queue = 0; - int64_t head = 0; - int64_t next = 0; - int64_t node = 0; - int64_t persistant_handle = 0; - v8::Error err2; - - envPtr = LookupConstant(target, "nodedbg_currentEnvironment", envPtr, err2); - process.ReadMemory(envPtr, &env, size, sberr); - - queue = LookupConstant(target, "nodedbg_class__Environment__handleWrapQueue", - queue, err2); - head = LookupConstant(target, "nodedbg_class__HandleWrapQueue__headOffset", - head, err2); - next = LookupConstant(target, "nodedbg_class__HandleWrapQueue__nextOffset", - next, err2); - node = LookupConstant(target, "nodedbg_class__HandleWrap__node", node, err2); - persistant_handle = - LookupConstant(target, "nodedbg_class__BaseObject__persistant_handle", - persistant_handle, err2); - - uint64_t buffer = 0; - bool go = true; if (!thread.IsValid()) { result.SetError("No valid process, please start something\n"); return false; } int activeHandles = 0; - uint64_t currentNode = env; - currentNode += queue; // XXX env.handle_wrap_queue_ - currentNode += head; // XXX env.handle_wrap_queue_.head_ - currentNode += next; // XXX env.handle_wrap_queue_.head_.next_ - process.ReadMemory(currentNode, &buffer, size, sberr); - currentNode = buffer; - // TODO needs a stop condition, currently it's being stopped by a break - while (go) { - addr_t myMemory = currentNode; - myMemory = myMemory - node; // wrap - myMemory += persistant_handle; - // XXX w->persistent().IsEmpty() - if (myMemory == 0) { + node::Environment env = node::Environment::GetCurrent(&nodeMod); + for (auto w : env.handle_wrap_queue()) { + if (w.persistent_addr() == 0) { continue; - } - - process.ReadMemory(myMemory, &buffer, size, sberr); - myMemory = buffer; - process.ReadMemory(myMemory, &buffer, size, sberr); - // TODO needs a better check - if (sberr.Fail()) { + } else if (w.persistent_addr() == -1) { + result.SetError("Failed to load persistent handle"); break; } - v8::JSObject v8_object(&llv8, buffer); + v8::JSObject v8_object(&llv8, w.v8_object_addr()); v8::Error err; std::string res = v8_object.Inspect(&inspect_options, err); if (err.Fail()) { - // result.SetError("Failed to evaluate expression"); + result.SetError("Failed to load object"); break; } activeHandles++; resultMsg << res.c_str() << std::endl; - - // XXX env.handle_wrap_queue_.head_.next_->next_->(...)->next_ - currentNode += next; - process.ReadMemory(currentNode, &buffer, size, sberr); - currentNode = buffer; } + result.Printf("Active handles: %d\n\n", activeHandles); result.Printf("%s", resultMsg.str().c_str()); return true; @@ -408,80 +368,37 @@ bool GetActiveRequestsCmd::DoExecute(SBDebugger d, char** cmd, inspect_options.detailed = true; llv8.Load(target); + nodeMod.Load(target); - int size = 8; - int64_t envPtr = 0; - uint64_t env = 0; - int64_t queue = 0; - int64_t head = 0; - int64_t next = 0; - int64_t node = 0; - int64_t persistant_handle = 0; - v8::Error err2; - - envPtr = LookupConstant(target, "nodedbg_currentEnvironment", envPtr, err2); - process.ReadMemory(envPtr, &env, size, sberr); - - queue = LookupConstant(target, "nodedbg_class__Environment__reqWrapQueue", - queue, err2); - head = LookupConstant(target, "nodedbg_class__ReqWrapQueue__headOffset", head, - err2); - next = LookupConstant(target, "nodedbg_class__ReqWrapQueue__nextOffset", next, - err2); - node = LookupConstant(target, "nodedbg_class__ReqWrap__node", node, err2); - persistant_handle = - LookupConstant(target, "nodedbg_class__BaseObject__persistant_handle", - persistant_handle, err2); - - uint64_t buffer = 0; - bool go = true; if (!thread.IsValid()) { result.SetError("No valid process, please start something\n"); return false; } int activeHandles = 0; - uint64_t currentNode = env; - currentNode += queue; // XXX env.handle_wrap_queue_ - currentNode += head; // XXX env.handle_wrap_queue_.head_ - currentNode += next; // XXX env.handle_wrap_queue_.head_.next_ - process.ReadMemory(currentNode, &buffer, size, sberr); - currentNode = buffer; - // TODO needs a stop condition - while (go) { - addr_t myMemory = currentNode; - myMemory = myMemory - node; - myMemory += persistant_handle; - // XXX w->persistent().IsEmpty() - if (myMemory == 0) { - continue; - } + node::Environment env = node::Environment::GetCurrent(&nodeMod); - process.ReadMemory(myMemory, &buffer, size, sberr); - myMemory = buffer; - process.ReadMemory(myMemory, &buffer, size, sberr); - // TODO needs a better check - if (sberr.Fail()) { + for (auto w : env.req_wrap_queue()) { + if (w.persistent_addr() == 0) { + continue; + } else if (w.persistent_addr() == -1) { + result.SetError("Failed to load persistent handle"); break; } - v8::JSObject v8_object(&llv8, buffer); + v8::JSObject v8_object(&llv8, w.v8_object_addr()); v8::Error err; std::string res = v8_object.Inspect(&inspect_options, err); if (err.Fail()) { - // result.SetError("Failed to evaluate expression"); + result.SetError("Failed to load object"); break; } activeHandles++; resultMsg << res.c_str() << std::endl; - - // env.handle_wrap_queue_.head_.next_->next_->(...)->next_ - currentNode += next; - process.ReadMemory(currentNode, &buffer, size, sberr); - currentNode = buffer; } - result.Printf("Active handles: %d\n\n", activeHandles); + + result.Printf("Active requests: %d\n\n", activeHandles); result.Printf("%s", resultMsg.str().c_str()); return true; } diff --git a/src/llv8-constants.cc b/src/llv8-constants.cc index c1da0bed..3b5d927d 100644 --- a/src/llv8-constants.cc +++ b/src/llv8-constants.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -23,7 +24,7 @@ using lldb::addr_t; static std::string kConstantPrefix = "v8dbg_"; -static bool IsDebugMode() { +bool IsDebugMode() { char* var = getenv("LLNODE_DEBUG"); if (var == nullptr) return false; @@ -41,7 +42,6 @@ void Module::Assign(SBTarget target, Common* common) { int64_t LookupConstant(SBTarget target, const char* name, int64_t def, Error& err) { int64_t res; - res = def; SBSymbolContextList context_list = target.FindSymbols(name); @@ -325,6 +325,9 @@ void Context::Load() { LoadConstant("class_Context__closure_index__int", "context_idx_closure"); kPreviousIndex = LoadConstant("class_Context__previous_index__int", "context_idx_prev"); + kNativeIndex = + LoadConstant("class_Context__native_index__int", "context_idx_native"); + kEmbedderDataIndex = LoadConstant("context_idx_embedder_data", (int)5); kMinContextSlots = LoadConstant("class_Context__min_context_slots__int", "context_min_slots"); } @@ -581,6 +584,14 @@ void Types::Load() { } } +void Isolate::Load() { + kThreadLocalTopOffset = LoadConstant("isolate_threadlocaltop_offset"); +} + +void ThreadLocalTop::Load() { + kContextOffset = LoadConstant("threadlocaltop_context_offset"); +} + } // namespace constants } // namespace v8 } // namespace llnode diff --git a/src/llv8-constants.h b/src/llv8-constants.h index a4c84a20..62aca4e7 100644 --- a/src/llv8-constants.h +++ b/src/llv8-constants.h @@ -12,7 +12,7 @@ namespace constants { int64_t LookupConstant(SBTarget target, const char* name, int64_t def, Error& err); - +bool IsDebugMode(); // Forward declarations class Common; @@ -219,6 +219,8 @@ class Context : public Module { int64_t kClosureIndex; int64_t kGlobalObjectIndex; int64_t kPreviousIndex; + int64_t kNativeIndex; + int64_t kEmbedderDataIndex; int64_t kMinContextSlots; protected: @@ -503,6 +505,24 @@ class Types : public Module { void Load(); }; +class Isolate : public Module { + public: + MODULE_DEFAULT_METHODS(Isolate); + int64_t kThreadLocalTopOffset; + + protected: + void Load(); +}; + +class ThreadLocalTop : public Module { + public: + MODULE_DEFAULT_METHODS(ThreadLocalTop); + int64_t kContextOffset; + + protected: + void Load(); +}; + #undef MODULE_DEFAULT_METHODS } // namespace constants diff --git a/src/llv8-inl.h b/src/llv8-inl.h index 3ec42fa2..94028366 100644 --- a/src/llv8-inl.h +++ b/src/llv8-inl.h @@ -454,6 +454,10 @@ inline Value Context::Previous(Error& err) { return FixedArray::Get(v8()->context()->kPreviousIndex, err); } +inline Value Context::Native(Error& err) { + return FixedArray::Get(v8()->context()->kNativeIndex, err); +} + inline Value Context::ContextSlot(int index, Error& err) { return FixedArray::Get(v8()->context()->kMinContextSlots + index, err); } diff --git a/src/llv8.cc b/src/llv8.cc index 1792435d..e2a11889 100644 --- a/src/llv8.cc +++ b/src/llv8.cc @@ -55,6 +55,8 @@ void LLV8::Load(SBTarget target) { name_dictionary.Assign(target, &common); frame.Assign(target, &common); types.Assign(target, &common); + isolate.Assign(target, &common); + thread_local_top.Assign(target, &common); } diff --git a/src/llv8.h b/src/llv8.h index 59f014f9..612dcdd0 100644 --- a/src/llv8.h +++ b/src/llv8.h @@ -5,6 +5,7 @@ #include +#include "src/constants.h" #include "src/llv8-constants.h" namespace llnode { @@ -379,6 +380,7 @@ class Context : public FixedArray { inline JSFunction Closure(Error& err); inline Value Previous(Error& err); + inline Value Native(Error& err); inline Value ContextSlot(int index, Error& err); std::string Inspect(Error& err); @@ -456,6 +458,10 @@ class LLV8 { void Load(lldb::SBTarget target); + constants::Isolate isolate; + constants::ThreadLocalTop thread_local_top; + constants::Context context; + private: template inline T LoadValue(int64_t addr, Error& err); @@ -483,7 +489,6 @@ class LLV8 { constants::SharedInfo shared_info; constants::Code code; constants::ScopeInfo scope_info; - constants::Context context; constants::Script script; constants::String string; constants::OneByteString one_byte_string; @@ -537,6 +542,7 @@ class LLV8 { friend class CodeMap; friend class llnode::FindJSObjectsVisitor; friend class llnode::FindReferencesCmd; + friend class llnode::constants::ConstantsWrapper; }; #undef V8_VALUE_DEFAULT_METHODS