Last active
September 3, 2018 14:49
-
-
Save mmarchini/647720e08468b8b96a7922f79c20c87e to your computer and use it in GitHub Desktop.
V8 Postmortem API Usage Example
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
#include <v8.h> | |
#include <v8-postmortem.h> | |
#include <napi.h> | |
#include <lldb/API/SBDebugger.h> | |
#include <lldb/API/SBTarget.h> | |
#include <lldb/API/SBProcess.h> | |
#include <iostream> | |
using lldb::addr_t; | |
bool LookupConstant(lldb::SBTarget target, const char* name, PostmortemTips* tips) { | |
lldb::SBSymbolContextList context_list = target.FindSymbols(name); | |
if (!context_list.IsValid() || context_list.GetSize() == 0) { | |
return false; | |
} | |
lldb::SBSymbolContext context = context_list.GetContextAtIndex(0); | |
lldb::SBSymbol symbol = context.GetSymbol(); | |
if (!symbol.IsValid()) { | |
return false; | |
} | |
lldb::SBAddress start = symbol.GetStartAddress(); | |
lldb::SBAddress end = symbol.GetEndAddress(); | |
uint32_t size = end.GetOffset() - start.GetOffset(); | |
if (size != sizeof(PostmortemTips)) { | |
return false; | |
} | |
lldb::SBError sberr; | |
target.ReadMemory(start, tips, size, sberr); | |
return true; | |
} | |
class DebuggerAnalyzer : public v8::PostmortemAnalyzer { | |
public: | |
explicit DebuggerAnalyzer(lldb::SBProcess* process) : process_(process) {}; | |
uintptr_t ReadPointer(const uintptr_t address) override { | |
lldb::SBError err; | |
std::cout << "reading pointer @ 0x" << std::hex << address << std::dec << std::endl; | |
auto ptr = process_->ReadPointerFromMemory(static_cast<addr_t>(address), err); | |
return static_cast<uintptr_t>(ptr); | |
} | |
private: | |
lldb::SBProcess* process_; | |
}; | |
Napi::String Heap(const Napi::CallbackInfo& info) { | |
Napi::Env env = info.Env(); | |
if (info.Length() < 2) { | |
Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); | |
return Napi::String::New(env, ""); | |
} | |
auto arg0 = info[0].As<Napi::String>(); | |
auto arg1 = info[1].As<Napi::String>(); | |
lldb::SBDebugger::Initialize(); | |
auto debugger = lldb::SBDebugger::Create(); | |
auto target = debugger.CreateTarget(std::string(arg0).c_str()); | |
if (!target.IsValid()) { | |
Napi::Error::New(env, "Invalid target").ThrowAsJavaScriptException(); | |
return Napi::String::New(env, ""); | |
} | |
auto process = target.LoadCore(std::string(arg1).c_str()); | |
SherlockAnalyzer analyzer(&process); | |
analyzer.Enable(); | |
PostmortemTips tips; | |
if (!LookupConstant(target, "v8dbg_postmortem_tips", &tips)) { | |
analyzer.Disable(); | |
Napi::Error::New(env, "Failed").ThrowAsJavaScriptException(); | |
return Napi::String::New(env, ""); | |
} | |
auto isolate = analyzer.Get<v8::Isolate*>(reinterpret_cast<uintptr_t>(tips.current_isolate)); | |
v8::PostmortemAnalyzer::HeapIterator heap_iterator(isolate); | |
v8::Value* val = nullptr; | |
std::cout << "Iterating the heap" << std::endl; | |
while ((val = heap_iterator.next()) != nullptr) { | |
if (val->IsObject()) std::cout << "Found an Object" << std::endl; | |
else std::cout << "Found something else" << std::endl; | |
} | |
std::cout << "Done" << std::endl; | |
analyzer.Disable(); | |
return Napi::String::New(env, std::string(arg0) + " - " + std::string(arg1)); | |
} | |
Napi::Object Init(Napi::Env env, Napi::Object exports) { | |
exports.Set(Napi::String::New(env, "heap"), Napi::Function::New(env, Heap)); | |
return exports; | |
} | |
NODE_API_MODULE(debugger, Init) |
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
#ifndef __DEBUGGER_H | |
#define __DEBUGGER_H | |
#include "v8-profiler.h" | |
#include <nan.h> | |
#include <node_object_wrap.h> | |
#include <fstream> | |
namespace node { | |
class Debugger : public Nan::ObjectWrap { | |
public: | |
static void Initialize(v8::Local<v8::Object> target); | |
static NAN_METHOD(New); | |
static NAN_METHOD(Heap); | |
Debugger() = default; | |
~Debugger() = default; | |
}; | |
}; | |
#endif // __DEBUGGER_H |
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
'use strict'; | |
const binding = require('./build/Release/debugger'); | |
module.exports = binding; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment