From 529b88af428081ea01ddc9efdd80845809149bcd Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 9 Mar 2018 18:37:46 +0800 Subject: [PATCH 1/2] test: fix hanging when testing with prepared core When the session is created by loading a prepared core dump, it should delete the target before quitting otherwise the process will prompt about deleting it and will hang if it does not receive an answer. --- test/common.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/common.js b/test/common.js index e1554f6f..e0dbed91 100644 --- a/test/common.js +++ b/test/common.js @@ -155,7 +155,7 @@ function Session(options) { debug('lldb binary:', lldbBin); if (options.scenario) { - this.needToKill = true; + this.needToKill = true; // need to send 'kill' when quitting // lldb -- node scenario.js const args = [ '--', @@ -173,7 +173,7 @@ function Session(options) { this.lldb.stdin.write(`plugin load "${exports.llnodePath}"\n`); this.lldb.stdin.write('run\n'); } else if (options.core) { - this.needToKill = false; + this.needToKill = false; // need to send 'target delete 0' when quitting debug('loading core', options.core); // lldb node -c core this.lldb = spawn(lldbBin, [], { @@ -262,8 +262,11 @@ Session.prototype.kill = function kill() { }; Session.prototype.quit = function quit() { - if (this.needToKill) + if (this.needToKill) { this.send('kill'); // kill the process launched in lldb + } else { + this.send('target delete 0'); // Delete the loaded core dump + } this.send('quit'); }; From de84f754136f9c4ba6516a8d1397fa675242ad65 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 16 Oct 2017 00:29:31 +0800 Subject: [PATCH 2/2] src: do not create global llscan or global llv8 - Eliminates all references to the global llscan in the commands, only instantiate one LLScan instance in llnode.cc and pass it down to all commands. - Eliminates all references to the global llv8, store it inside the LLScan instead, because LLScan must need a valid llv8 (with postmortem metadata loaded) to function. - Only instantiate a static LLScan and a static LLV8 during plugin initialization. --- src/llnode.cc | 44 +++++++++---------- src/llnode.h | 11 ++++- src/llscan.cc | 114 +++++++++++++++++++++++++------------------------- src/llscan.h | 36 +++++++++++++--- 4 files changed, 120 insertions(+), 85 deletions(-) diff --git a/src/llnode.cc b/src/llnode.cc index 92cc9ff6..4a9cc7d1 100644 --- a/src/llnode.cc +++ b/src/llnode.cc @@ -27,8 +27,6 @@ using lldb::SBValue; using lldb::eReturnStatusFailed; using lldb::eReturnStatusSuccessFinishResult; -v8::LLV8 llv8; - char** CommandBase::ParseInspectOptions(char** cmd, v8::Value::InspectOptions* options) { static struct option opts[] = { @@ -105,7 +103,7 @@ bool BacktraceCmd::DoExecute(SBDebugger d, char** cmd, } // Load V8 constants from postmortem data - llv8.Load(target); + llv8_->Load(target); { SBStream desc; @@ -124,7 +122,7 @@ bool BacktraceCmd::DoExecute(SBDebugger d, char** cmd, if (!frame.GetSymbol().IsValid()) { v8::Error err; - v8::JSFrame v8_frame(&llv8, static_cast(frame.GetFP())); + v8::JSFrame v8_frame(llv8_, static_cast(frame.GetFP())); std::string res = v8_frame.Inspect(true, err); if (err.Success()) { result.Printf(" %c frame #%u: 0x%016" PRIx64 " %s\n", star, i, pc, @@ -196,9 +194,9 @@ bool PrintCmd::DoExecute(SBDebugger d, char** cmd, } // Load V8 constants from postmortem data - llv8.Load(target); + llv8_->Load(target); - v8::Value v8_value(&llv8, value.GetValueAsSigned()); + v8::Value v8_value(llv8_, value.GetValueAsSigned()); v8::Error err; std::string res = v8_value.Inspect(&inspect_options, err); if (err.Fail()) { @@ -255,7 +253,7 @@ bool ListCmd::DoExecute(SBDebugger d, char** cmd, } // Load V8 constants from postmortem data - llv8.Load(target); + llv8_->Load(target); SBFrame frame = thread.GetSelectedFrame(); SBSymbol symbol = frame.GetSymbol(); @@ -279,7 +277,7 @@ bool ListCmd::DoExecute(SBDebugger d, char** cmd, // V8 frame v8::Error err; - v8::JSFrame v8_frame(&llv8, static_cast(frame.GetFP())); + v8::JSFrame v8_frame(llv8_, static_cast(frame.GetFP())); const static uint32_t kDisplayLines = 4; std::string* lines = new std::string[kDisplayLines]; @@ -319,26 +317,29 @@ namespace lldb { bool PluginInitialize(SBDebugger d) { llnode::InitDebugMode(); + static llnode::v8::LLV8 llv8; + static llnode::LLScan llscan = llnode::LLScan(&llv8); + SBCommandInterpreter interpreter = d.GetCommandInterpreter(); SBCommand v8 = interpreter.AddMultiwordCommand("v8", "Node.js helpers"); v8.AddCommand( - "bt", new llnode::BacktraceCmd(), + "bt", new llnode::BacktraceCmd(&llv8), "Show a backtrace with node.js JavaScript functions and their args. " "An optional argument is accepted; if that argument is a number, it " "specifies the number of frames to display. Otherwise all frames will " "be dumped.\n\n" "Syntax: v8 bt [number]\n"); - interpreter.AddCommand("jsstack", new llnode::BacktraceCmd(), + interpreter.AddCommand("jsstack", new llnode::BacktraceCmd(&llv8), "Alias for `v8 bt`"); - v8.AddCommand("print", new llnode::PrintCmd(false), + v8.AddCommand("print", new llnode::PrintCmd(&llv8, false), "Print short description of the JavaScript value.\n\n" "Syntax: v8 print expr\n"); v8.AddCommand( - "inspect", new llnode::PrintCmd(true), + "inspect", new llnode::PrintCmd(&llv8, true), "Print detailed description and contents of the JavaScript value.\n\n" "Possible flags (all optional):\n\n" " * -F, --full-string - print whole string without adding ellipsis\n" @@ -348,18 +349,18 @@ bool PluginInitialize(SBDebugger d) { "string/array\n" "\n" "Syntax: v8 inspect [flags] expr\n"); - interpreter.AddCommand("jsprint", new llnode::PrintCmd(true), + interpreter.AddCommand("jsprint", new llnode::PrintCmd(&llv8, true), "Alias for `v8 inspect`"); SBCommand source = v8.AddMultiwordCommand("source", "Source code information"); - source.AddCommand("list", new llnode::ListCmd(), + source.AddCommand("list", new llnode::ListCmd(&llv8), "Print source lines around a selected JavaScript frame.\n\n" "Syntax: v8 source list\n"); - interpreter.AddCommand("jssource", new llnode::ListCmd(), + interpreter.AddCommand("jssource", new llnode::ListCmd(&llv8), "Alias for `v8 source list`"); - v8.AddCommand("findjsobjects", new llnode::FindObjectsCmd(), + v8.AddCommand("findjsobjects", new llnode::FindObjectsCmd(&llscan), "List all object types and instance counts grouped by type " "name and sorted by instance count. Use -d or --detailed to " "get an output grouped by type name, properties, and array " @@ -373,23 +374,24 @@ bool PluginInitialize(SBDebugger d) { #endif // LLDB_SBMemoryRegionInfoList_h_ ); - interpreter.AddCommand("findjsobjects", new llnode::FindObjectsCmd(), + interpreter.AddCommand("findjsobjects", new llnode::FindObjectsCmd(&llscan), "Alias for `v8 findjsobjects`"); - v8.AddCommand("findjsinstances", new llnode::FindInstancesCmd(), + v8.AddCommand("findjsinstances", new llnode::FindInstancesCmd(&llscan, false), "List every object with the specified type name.\n" "Use -v or --verbose to display detailed `v8 inspect` output " "for each object.\n" "Accepts the same options as `v8 inspect`"); - interpreter.AddCommand("findjsinstances", new llnode::FindInstancesCmd(), + interpreter.AddCommand("findjsinstances", + new llnode::FindInstancesCmd(&llscan, false), "List all objects which share the specified map.\n"); - v8.AddCommand("nodeinfo", new llnode::NodeInfoCmd(), + v8.AddCommand("nodeinfo", new llnode::NodeInfoCmd(&llscan), "Print information about Node.js\n"); v8.AddCommand( - "findrefs", new llnode::FindReferencesCmd(), + "findrefs", new llnode::FindReferencesCmd(&llscan), "Finds all the object properties which meet the search criteria.\n" "The default is to list all the object properties that reference the " "specified value.\n" diff --git a/src/llnode.h b/src/llnode.h index b46bc7ef..5340571c 100644 --- a/src/llnode.h +++ b/src/llnode.h @@ -16,15 +16,19 @@ class CommandBase : public lldb::SBCommandPluginInterface { class BacktraceCmd : public CommandBase { public: + BacktraceCmd(v8::LLV8* llv8) : llv8_(llv8) {} ~BacktraceCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, lldb::SBCommandReturnObject& result) override; + + private: + v8::LLV8* llv8_; }; class PrintCmd : public CommandBase { public: - PrintCmd(bool detailed) : detailed_(detailed) {} + PrintCmd(v8::LLV8* llv8, bool detailed) : llv8_(llv8), detailed_(detailed) {} ~PrintCmd() override {} @@ -32,15 +36,20 @@ class PrintCmd : public CommandBase { lldb::SBCommandReturnObject& result) override; private: + v8::LLV8* llv8_; bool detailed_; }; class ListCmd : public CommandBase { public: + ListCmd(v8::LLV8* llv8) : llv8_(llv8) {} ~ListCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, lldb::SBCommandReturnObject& result) override; + + private: + v8::LLV8* llv8_; }; } // namespace llnode diff --git a/src/llscan.cc b/src/llscan.cc index 010621a5..dd2a6a7d 100644 --- a/src/llscan.cc +++ b/src/llscan.cc @@ -13,7 +13,6 @@ #include "src/llnode.h" #include "src/llscan.h" #include "src/llv8-inl.h" -#include "src/llv8.h" namespace llnode { @@ -28,12 +27,6 @@ using lldb::SBValue; using lldb::eReturnStatusFailed; using lldb::eReturnStatusSuccessFinishResult; -// Defined in llnode.cc -extern v8::LLV8 llv8; - -LLScan llscan; - - bool FindObjectsCmd::DoExecute(SBDebugger d, char** cmd, SBCommandReturnObject& result) { SBTarget target = d.GetSelectedTarget(); @@ -42,8 +35,11 @@ bool FindObjectsCmd::DoExecute(SBDebugger d, char** cmd, return false; } + // Load V8 constants from postmortem data + llscan_->v8()->Load(target); + /* Ensure we have a map of objects. */ - if (!llscan.ScanHeapForObjects(target, result)) { + if (!llscan_->ScanHeapForObjects(target, result)) { result.SetStatus(eReturnStatusFailed); return false; } @@ -67,8 +63,8 @@ void FindObjectsCmd::SimpleOutput(SBCommandReturnObject& result) { * TODO(hhellyer) - Make sort type an option (by count, size or name) */ std::vector sorted_by_count; - TypeRecordMap::iterator end = llscan.GetMapsToInstances().end(); - for (TypeRecordMap::iterator it = llscan.GetMapsToInstances().begin(); + TypeRecordMap::iterator end = llscan_->GetMapsToInstances().end(); + for (TypeRecordMap::iterator it = llscan_->GetMapsToInstances().begin(); it != end; ++it) { sorted_by_count.push_back(it->second); } @@ -98,7 +94,7 @@ void FindObjectsCmd::SimpleOutput(SBCommandReturnObject& result) { void FindObjectsCmd::DetailedOutput(SBCommandReturnObject& result) { std::vector sorted_by_count; - for (auto kv : llscan.GetDetailedMapsToInstances()) { + for (auto kv : llscan_->GetDetailedMapsToInstances()) { sorted_by_count.push_back(kv.second); } @@ -142,8 +138,11 @@ bool FindInstancesCmd::DoExecute(SBDebugger d, char** cmd, return false; } + // Load V8 constants from postmortem data + llscan_->v8()->Load(target); + /* Ensure we have a map of objects. */ - if (!llscan.ScanHeapForObjects(target, result)) { + if (!llscan_->ScanHeapForObjects(target, result)) { result.SetStatus(eReturnStatusFailed); return false; } @@ -159,17 +158,14 @@ bool FindInstancesCmd::DoExecute(SBDebugger d, char** cmd, std::string type_name = full_cmd; - // Load V8 constants from postmortem data - llv8.Load(target); - TypeRecordMap::iterator instance_it = - llscan.GetMapsToInstances().find(type_name); - if (instance_it != llscan.GetMapsToInstances().end()) { + llscan_->GetMapsToInstances().find(type_name); + if (instance_it != llscan_->GetMapsToInstances().end()) { TypeRecord* t = instance_it->second; for (std::set::iterator it = t->GetInstances().begin(); it != t->GetInstances().end(); ++it) { v8::Error err; - v8::Value v8_value(&llv8, *it); + v8::Value v8_value(llscan_->v8(), *it); std::string res = v8_value.Inspect(&inspect_options, err); result.Printf("%s\n", res.c_str()); } @@ -193,24 +189,27 @@ bool NodeInfoCmd::DoExecute(SBDebugger d, char** cmd, return false; } + // Load V8 constants from postmortem data + llscan_->v8()->Load(target); + /* Ensure we have a map of objects. */ - if (!llscan.ScanHeapForObjects(target, result)) { + if (!llscan_->ScanHeapForObjects(target, result)) { return false; } std::string process_type_name("process"); TypeRecordMap::iterator instance_it = - llscan.GetMapsToInstances().find(process_type_name); + llscan_->GetMapsToInstances().find(process_type_name); - if (instance_it != llscan.GetMapsToInstances().end()) { + if (instance_it != llscan_->GetMapsToInstances().end()) { TypeRecord* t = instance_it->second; for (std::set::iterator it = t->GetInstances().begin(); it != t->GetInstances().end(); ++it) { v8::Error err; // The properties object should be a JSObject - v8::JSObject process_obj(&llv8, *it); + v8::JSObject process_obj(llscan_->v8(), *it); v8::Value pid_val = process_obj.GetProperty("pid", err); @@ -370,6 +369,9 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, return false; } + // Load V8 constants from postmortem data + llscan_->v8()->Load(target); + // Default scan type. ScanType type = ScanType::kFieldValue; @@ -381,9 +383,6 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, return false; } - // Load V8 constants from postmortem data - llv8.Load(target); - ObjectScanner* scanner; switch (type) { @@ -402,14 +401,14 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, return false; } // Check the address we've been given at least looks like a valid object. - v8::Value search_value(&llv8, value.GetValueAsSigned()); + v8::Value search_value(llscan_->v8(), value.GetValueAsSigned()); v8::Smi smi(search_value); if (smi.Check()) { result.SetError("Search value is an SMI."); result.SetStatus(eReturnStatusFailed); return false; } - scanner = new ReferenceScanner(search_value); + scanner = new ReferenceScanner(llscan_, search_value); break; } case ScanType::kPropertyName: { @@ -420,7 +419,7 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, return false; } std::string property_name = start[0]; - scanner = new PropertyScanner(property_name); + scanner = new PropertyScanner(llscan_, property_name); break; } case ScanType::kStringValue: { @@ -431,7 +430,7 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, return false; } std::string string_value = start[0]; - scanner = new StringScanner(string_value); + scanner = new StringScanner(llscan_, string_value); break; } /* We can add options to the command and further sub-classes of @@ -450,7 +449,7 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, * (Do this after we've checked the options to avoid * a long pause before reporting an error.) */ - if (!llscan.ScanHeapForObjects(target, result)) { + if (!llscan_->ScanHeapForObjects(target, result)) { delete scanner; result.SetStatus(eReturnStatusFailed); return false; @@ -471,12 +470,12 @@ bool FindReferencesCmd::DoExecute(SBDebugger d, char** cmd, void FindReferencesCmd::ScanForReferences(ObjectScanner* scanner) { // Walk all the object instances and handle them according to their type. - TypeRecordMap mapstoinstances = llscan.GetMapsToInstances(); + TypeRecordMap mapstoinstances = llscan_->GetMapsToInstances(); for (auto const entry : mapstoinstances) { TypeRecord* typerecord = entry.second; for (uint64_t addr : typerecord->GetInstances()) { v8::Error err; - v8::Value obj_value(&llv8, addr); + v8::Value obj_value(llscan_->v8(), addr); v8::HeapObject heap_object(obj_value); int64_t type = heap_object.GetType(err); v8::LLV8* v8 = heap_object.v8(); @@ -512,10 +511,10 @@ void FindReferencesCmd::PrintReferences(SBCommandReturnObject& result, ReferencesVector* references, ObjectScanner* scanner) { // Walk all the object instances and handle them according to their type. - TypeRecordMap mapstoinstances = llscan.GetMapsToInstances(); + TypeRecordMap mapstoinstances = llscan_->GetMapsToInstances(); for (uint64_t addr : *references) { v8::Error err; - v8::Value obj_value(&llv8, addr); + v8::Value obj_value(llscan_->v8(), addr); v8::HeapObject heap_object(obj_value); int64_t type = heap_object.GetType(err); v8::LLV8* v8 = heap_object.v8(); @@ -694,7 +693,7 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::JSObject& js_obj, if (!err.Success()) break; if (already_saved.count(v.raw())) continue; - references = llscan.GetReferencesByValue(v.raw()); + references = llscan_->GetReferencesByValue(v.raw()); references->push_back(js_obj.raw()); already_saved.insert(v.raw()); } @@ -711,7 +710,7 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::JSObject& js_obj, if (already_saved.count(v.raw())) continue; - references = llscan.GetReferencesByValue(v.raw()); + references = llscan_->GetReferencesByValue(v.raw()); references->push_back(js_obj.raw()); already_saved.insert(v.raw()); } @@ -735,7 +734,7 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::String& str, v8::String parent = sliced_str.Parent(err); if (err.Success()) { - references = llscan.GetReferencesByValue(parent.raw()); + references = llscan_->GetReferencesByValue(parent.raw()); references->push_back(str.raw()); } @@ -744,13 +743,13 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::String& str, v8::String first = cons_str.First(err); if (err.Success()) { - references = llscan.GetReferencesByValue(first.raw()); + references = llscan_->GetReferencesByValue(first.raw()); references->push_back(str.raw()); } v8::String second = cons_str.Second(err); if (err.Success() && first.raw() != second.raw()) { - references = llscan.GetReferencesByValue(second.raw()); + references = llscan_->GetReferencesByValue(second.raw()); references->push_back(str.raw()); } } else if (repr == v8->string()->kThinStringTag) { @@ -758,7 +757,7 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::String& str, v8::String actual = thin_str.Actual(err); if (err.Success()) { - references = llscan.GetReferencesByValue(actual.raw()); + references = llscan_->GetReferencesByValue(actual.raw()); references->push_back(str.raw()); } } @@ -767,12 +766,12 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::String& str, bool FindReferencesCmd::ReferenceScanner::AreReferencesLoaded() { - return llscan.AreReferencesByValueLoaded(); + return llscan_->AreReferencesByValueLoaded(); } ReferencesVector* FindReferencesCmd::ReferenceScanner::GetReferences() { - return llscan.GetReferencesByValue(search_value_.raw()); + return llscan_->GetReferencesByValue(search_value_.raw()); } @@ -820,19 +819,19 @@ void FindReferencesCmd::PropertyScanner::ScanRefs(v8::JSObject& js_obj, if (err.Fail()) { continue; } - references = llscan.GetReferencesByProperty(key); + references = llscan_->GetReferencesByProperty(key); references->push_back(js_obj.raw()); } } bool FindReferencesCmd::PropertyScanner::AreReferencesLoaded() { - return llscan.AreReferencesByPropertyLoaded(); + return llscan_->AreReferencesByPropertyLoaded(); } ReferencesVector* FindReferencesCmd::PropertyScanner::GetReferences() { - return llscan.GetReferencesByProperty(search_value_); + return llscan_->GetReferencesByProperty(search_value_); } @@ -999,7 +998,7 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::JSObject& js_obj, if (already_saved.count(value)) continue; - references = llscan.GetReferencesByString(value); + references = llscan_->GetReferencesByString(value); references->push_back(js_obj.raw()); already_saved.insert(value); } @@ -1024,7 +1023,7 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::JSObject& js_obj, } if (already_saved.count(value)) continue; - references = llscan.GetReferencesByString(value); + references = llscan_->GetReferencesByString(value); references->push_back(js_obj.raw()); already_saved.insert(value); } @@ -1050,7 +1049,7 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::String& str, if (err.Fail()) return; std::string parent = parent_str.ToString(err); if (err.Success()) { - references = llscan.GetReferencesByString(parent); + references = llscan_->GetReferencesByString(parent); references->push_back(str.raw()); } } else if (repr == v8->string()->kConsStringTag) { @@ -1069,7 +1068,7 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::String& str, std::string first = first_str.ToString(err); if (err.Success()) { - references = llscan.GetReferencesByString(first); + references = llscan_->GetReferencesByString(first); references->push_back(str.raw()); } } @@ -1087,7 +1086,7 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::String& str, std::string second = second_str.ToString(err); if (err.Success()) { - references = llscan.GetReferencesByString(second); + references = llscan_->GetReferencesByString(second); references->push_back(str.raw()); } } @@ -1098,12 +1097,12 @@ void FindReferencesCmd::StringScanner::ScanRefs(v8::String& str, bool FindReferencesCmd::StringScanner::AreReferencesLoaded() { - return llscan.AreReferencesByStringLoaded(); + return llscan_->AreReferencesByStringLoaded(); } ReferencesVector* FindReferencesCmd::StringScanner::GetReferences() { - return llscan.GetReferencesByString(search_value_); + return llscan_->GetReferencesByString(search_value_); } @@ -1111,14 +1110,12 @@ FindJSObjectsVisitor::FindJSObjectsVisitor(SBTarget& target, LLScan* llscan) : target_(target), llscan_(llscan) { found_count_ = 0; address_byte_size_ = target_.GetProcess().GetAddressByteSize(); - // Load V8 constants from postmortem data - llv8.Load(target); } /* Visit every address, a bit brute force but it works. */ uint64_t FindJSObjectsVisitor::Visit(uint64_t location, uint64_t word) { - v8::Value v8_value(&llv8, word); + v8::Value v8_value(llscan_->v8(), word); v8::Error err; // Test if this is SMI @@ -1136,7 +1133,7 @@ uint64_t FindJSObjectsVisitor::Visit(uint64_t location, uint64_t word) { MapCacheEntry map_info; if (map_cache_.count(map.raw()) == 0) { - map_info.Load(map, heap_object, err); + map_info.Load(map, heap_object, llscan_->v8(), err); if (err.Fail()) { return address_byte_size_; } @@ -1309,6 +1306,7 @@ FindJSObjectsVisitor::MapCacheEntry::GetTypeNameWithProperties( bool FindJSObjectsVisitor::MapCacheEntry::Load(v8::Map map, v8::HeapObject heap_object, + v8::LLV8* llv8, v8::Error& err) { // Check type first is_histogram = FindJSObjectsVisitor::IsAHistogramType(map, err); @@ -1325,8 +1323,8 @@ bool FindJSObjectsVisitor::MapCacheEntry::Load(v8::Map map, int64_t type = heap_object.GetType(err); indexed_properties_count_ = 0; - if (v8::JSObject::IsObjectType(&llv8, type) || - (type == llv8.types()->kJSArrayType)) { + if (v8::JSObject::IsObjectType(llv8, type) || + (type == llv8->types()->kJSArrayType)) { v8::JSObject js_obj(heap_object); indexed_properties_count_ = js_obj.GetArrayLength(err); if (err.Fail()) return false; diff --git a/src/llscan.h b/src/llscan.h index 9ee03f4c..b1cf1abb 100644 --- a/src/llscan.h +++ b/src/llscan.h @@ -19,6 +19,7 @@ typedef std::map ReferencesByStringMap; class FindObjectsCmd : public CommandBase { public: + FindObjectsCmd(LLScan* llscan) : llscan_(llscan) {} ~FindObjectsCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, @@ -26,29 +27,40 @@ class FindObjectsCmd : public CommandBase { void SimpleOutput(lldb::SBCommandReturnObject& result); void DetailedOutput(lldb::SBCommandReturnObject& result); + + private: + LLScan* llscan_; }; class FindInstancesCmd : public CommandBase { public: + FindInstancesCmd(LLScan* llscan, bool detailed) + : llscan_(llscan), detailed_(detailed) {} ~FindInstancesCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, lldb::SBCommandReturnObject& result) override; private: + LLScan* llscan_; bool detailed_; }; class NodeInfoCmd : public CommandBase { public: + NodeInfoCmd(LLScan* llscan) : llscan_(llscan) {} ~NodeInfoCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, lldb::SBCommandReturnObject& result) override; + + private: + LLScan* llscan_; }; class FindReferencesCmd : public CommandBase { public: + FindReferencesCmd(LLScan* llscan) : llscan_(llscan) {} ~FindReferencesCmd() override {} bool DoExecute(lldb::SBDebugger d, char** cmd, @@ -82,7 +94,8 @@ class FindReferencesCmd : public CommandBase { class ReferenceScanner : public ObjectScanner { public: - ReferenceScanner(v8::Value search_value) : search_value_(search_value) {} + ReferenceScanner(LLScan* llscan, v8::Value search_value) + : llscan_(llscan), search_value_(search_value) {} bool AreReferencesLoaded() override; @@ -97,12 +110,14 @@ class FindReferencesCmd : public CommandBase { v8::Error& err) override; private: + LLScan* llscan_; v8::Value search_value_; }; class PropertyScanner : public ObjectScanner { public: - PropertyScanner(std::string search_value) : search_value_(search_value) {} + PropertyScanner(LLScan* llscan, std::string search_value) + : llscan_(llscan), search_value_(search_value) {} bool AreReferencesLoaded() override; @@ -116,13 +131,15 @@ class FindReferencesCmd : public CommandBase { v8::Error& err) override; private: + LLScan* llscan_; std::string search_value_; }; class StringScanner : public ObjectScanner { public: - StringScanner(std::string search_value) : search_value_(search_value) {} + StringScanner(LLScan* llscan, std::string search_value) + : llscan_(llscan), search_value_(search_value) {} bool AreReferencesLoaded() override; @@ -137,8 +154,12 @@ class FindReferencesCmd : public CommandBase { v8::Error& err) override; private: + LLScan* llscan_; std::string search_value_; }; + + private: + LLScan* llscan_; // FindReferencesCmd::llscan_ }; class MemoryVisitor { @@ -236,7 +257,8 @@ class FindJSObjectsVisitor : MemoryVisitor { ShowArrayLength show_array_length = kShowArrayLength, size_t max_properties = 0); - bool Load(v8::Map map, v8::HeapObject heap_object, v8::Error& err); + bool Load(v8::Map map, v8::HeapObject heap_object, + v8::LLV8* llv8, v8::Error& err); }; static bool IsAHistogramType(v8::Map& map, v8::Error& err); @@ -259,7 +281,9 @@ class FindJSObjectsVisitor : MemoryVisitor { class LLScan { public: - LLScan() {} + LLScan(v8::LLV8* llv8) : llv8_(llv8) {} + + v8::LLV8* v8() { return llv8_; } bool ScanHeapForObjects(lldb::SBTarget target, lldb::SBCommandReturnObject& result); @@ -302,6 +326,8 @@ class LLScan { return references_by_string_[string_value]; }; + v8::LLV8* llv8_; + private: void ScanMemoryRanges(FindJSObjectsVisitor& v); void ClearMemoryRanges();