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 defe8f4f..4432c762 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) { @@ -317,79 +321,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; @@ -406,80 +366,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 17ce135f..00f7e760 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); @@ -311,6 +311,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"); } @@ -553,6 +556,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 8cff8ed4..3e6b84a9 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: @@ -481,6 +483,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 47281eea..3c633021 100644 --- a/src/llv8-inl.h +++ b/src/llv8-inl.h @@ -423,6 +423,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 d05a79d7..a7014a85 100644 --- a/src/llv8.cc +++ b/src/llv8.cc @@ -54,6 +54,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 008e09da..9aadb8de 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 { @@ -365,6 +366,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); @@ -443,6 +445,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); @@ -469,7 +475,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; @@ -519,6 +524,7 @@ class LLV8 { friend class CodeMap; friend class llnode::FindJSObjectsVisitor; friend class llnode::FindReferencesCmd; + friend class llnode::constants::ConstantsWrapper; }; #undef V8_VALUE_DEFAULT_METHODS