/* * Prototype: * Stalker.addCallProbe(target_address, callback) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_stalker_on_add_call_probe (const FunctionCallbackInfo<Value> & info) { GumV8Stalker * self = static_cast<GumV8Stalker *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); GumV8CallProbe * probe; GumProbeId id; gpointer target_address; if (!_gum_v8_native_pointer_get (info[0], &target_address, self->core)) return; Local<Value> callback_value = info[1]; if (!callback_value->IsFunction ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Stalker.addCallProbe: second argument must be a function"))); return; } Local<Function> callback = Local<Function>::Cast (callback_value); probe = g_slice_new (GumV8CallProbe); probe->parent = self; probe->callback = new GumPersistent<Function>::type (isolate, callback); probe->receiver = new GumPersistent<Value>::type (isolate, info.This ()); id = gum_stalker_add_call_probe (_gum_v8_stalker_get (self), target_address, gum_v8_call_probe_fire, probe, reinterpret_cast<GDestroyNotify> (gum_v8_call_probe_free)); info.GetReturnValue ().Set (id); }
/* * Prototype: * Module.findBaseAddress(module_name) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_module_on_find_base_address ( const FunctionCallbackInfo<Value> & info) { GumV8Module * self = static_cast<GumV8Module *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); Local<Value> module_name_val = info[0]; if (!module_name_val->IsString ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Module.findBaseAddress: argument must be a string " "specifying module name"))); return; } String::Utf8Value module_name (module_name_val); GumAddress raw_address = gum_module_find_base_address (*module_name); if (raw_address != 0) { info.GetReturnValue ().Set ( _gum_v8_native_pointer_new (GSIZE_TO_POINTER (raw_address), self->core)); } else { info.GetReturnValue ().SetNull (); } }
void ConsoleInterfaces::Assert(const FunctionCallbackInfo<Value>& args) { Handle<External> ext = Handle<External>::Cast(args.Data()); Flathead *pFH = (Flathead *)ext->Value(); int counter = 0; if (args.Length() == 0) { pFH->GetConfiguration()->LoggingFn()(LogLevels::Assert, ""); return; } Local<Value> value = args[0]; if (value->IsTrue()) { args.GetReturnValue().Set(counter); return; } if (pFH->GetConfiguration()->LoggingFn() != NULL) { for (int i = 1; i < args.Length(); i++) { Local<Value> value = args[i]; String::Utf8Value outputString(value); pFH->GetConfiguration()->LoggingFn()(LogLevels::Assert, *outputString); counter++; } } args.GetReturnValue().Set(counter); }
void Proxy::getProperty(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); // The name of the property can be passed either as // an argument or a data parameter. Local<String> name; if (args.Length() >= 1) { name = args[0]->ToString(isolate); } else if (args.Data()->IsString()) { name = args.Data().As<String>(); } else { JSException::Error(isolate, "Requires property name."); return; } args.GetReturnValue().Set(getPropertyForProxy(isolate, name, args.Holder())); }
/* * Prototype: * Stalker.garbageCollect() * * Docs: * TBW * * Example: * TBW */ static void gum_v8_stalker_on_garbage_collect (const FunctionCallbackInfo<Value> & info) { GumV8Stalker * self = static_cast<GumV8Stalker *> ( info.Data ().As<External> ()->Value ()); gum_stalker_garbage_collect (_gum_v8_stalker_get (self)); }
/* * Prototype: * Module.enumerateImports(name, callback) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_module_on_enumerate_imports ( const FunctionCallbackInfo<Value> & info) { GumV8Module * self = static_cast<GumV8Module *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); GumV8ImportsContext ctx; ctx.self = self; ctx.isolate = isolate; Local<Value> name_val = info[0]; if (!name_val->IsString ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Module.enumerateImports: first argument must be " "a string specifying a module name whose imports to enumerate"))); return; } String::Utf8Value name_str (name_val); Local<Value> callbacks_value = info[1]; if (!callbacks_value->IsObject ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Module.enumerateImports: second argument must be " "a callback object"))); return; } Local<Object> callbacks = Local<Object>::Cast (callbacks_value); if (!_gum_v8_callbacks_get (callbacks, "onMatch", &ctx.on_match, ctx.self->core)) { return; } if (!_gum_v8_callbacks_get (callbacks, "onComplete", &ctx.on_complete, ctx.self->core)) { return; } ctx.receiver = info.This (); ctx.imp = eternal_imp.Get (isolate); ctx.type = eternal_type.Get (isolate); ctx.name = eternal_name.Get (isolate); ctx.module = eternal_module.Get (isolate); ctx.address = eternal_address.Get (isolate); ctx.variable = eternal_variable.Get (isolate); gum_module_enumerate_imports (*name_str, gum_v8_module_handle_import_match, &ctx); ctx.on_complete->Call (ctx.receiver, 0, 0); }
void ModulePhysics::jsVelocity(const FunctionCallbackInfo<Value> &args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); ModulePhysics *module = (ModulePhysics*)HelperScript::Unwrap(args.Data()); if (args.Length() < 1 || !args[0]->IsString()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "first argument must be entity id as string"))); return; } uint64_t id = stoull(*String::Utf8Value(args[0])); if (!id) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "invalid entity id"))); return; } auto frm = module->Entity->Get<Form>(id); if (!frm) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "entity has no form property"))); return; } // set velocity if(args.Length() > 1) { btVector3 velocity; if (args.Length() > 3) { if (!args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second, third and fourth arguments must be velocity values as numbers"))); return; } velocity = btVector3((float)args[1]->NumberValue(), (float)args[2]->NumberValue(), (float)args[3]->NumberValue()); } else if (args.Length() > 1) { if (!args[1]->IsNumber()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second argument must be a velocity as number"))); return; } velocity = btVector3(0, (float)args[1]->NumberValue(), 0); } else { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second or second, third and fourth arguments must be velocity values as numbers"))); return; } frm->Body->activate(); frm->Body->setLinearVelocity(velocity); } // get velocity else { btVector3 velocity = frm->Body->getLinearVelocity(); Handle<Array> result = Array::New(isolate, 3); result->Set(0, Number::New(isolate, velocity.getX())); result->Set(1, Number::New(isolate, velocity.getY())); result->Set(2, Number::New(isolate, velocity.getZ())); args.GetReturnValue().Set(result); } }
/* * Prototype: * Module.findExportByName(module_name, symbol_name) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_module_on_find_export_by_name ( const FunctionCallbackInfo<Value> & info) { GumV8Module * self = static_cast<GumV8Module *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); Local<Value> module_name_val = info[0]; gchar * module_name; if (module_name_val->IsString ()) { String::Utf8Value module_name_utf8 (module_name_val); module_name = g_strdup (*module_name_utf8); } else if (module_name_val->IsNull ()) { module_name = NULL; } else { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Module.findExportByName: first argument must be a string " "specifying module name, or null"))); return; } Local<Value> symbol_name_val = info[1]; if (!symbol_name_val->IsString ()) { g_free (module_name); isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Module.findExportByName: second argument must be a string " "specifying name of exported symbol"))); return; } String::Utf8Value symbol_name (symbol_name_val); GumAddress raw_address = gum_module_find_export_by_name (module_name, *symbol_name); if (raw_address != 0) { info.GetReturnValue ().Set ( _gum_v8_native_pointer_new (GSIZE_TO_POINTER (raw_address), self->core)); } else { info.GetReturnValue ().SetNull (); } g_free (module_name); }
/** * TJSオブジェクトのコンストラクタ */ void TJSInstance::tjsConstructor(const FunctionCallbackInfo<Value>& args) { Isolate *isolate = args.GetIsolate(); HandleScope handle_scope(isolate); tTJSVariant classObj; if (getVariant(isolate, classObj, args.Data()->ToObject())) { CreateInfo info(classObj, args); args.GetReturnValue().Set(info.create()); return; } args.GetReturnValue().Set(ERROR_BADINSTANCE(isolate)); }
/* * Prototype: * Module.enumerateRanges(name, prot, callback) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_module_on_enumerate_ranges (const FunctionCallbackInfo<Value> & info) { GumV8RangesContext ctx; ctx.self = static_cast<GumV8Module *> ( info.Data ().As<External> ()->Value ()); ctx.isolate = info.GetIsolate (); Local<Value> name_val = info[0]; if (!name_val->IsString ()) { ctx.isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( ctx.isolate, "Module.enumerateRanges: first argument must be " "a string specifying a module name whose ranges to enumerate"))); return; } String::Utf8Value name_str (name_val); GumPageProtection prot; if (!_gum_v8_page_protection_get (info[1], &prot, ctx.self->core)) return; Local<Value> callbacks_value = info[2]; if (!callbacks_value->IsObject ()) { ctx.isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( ctx.isolate, "Module.enumerateRanges: third argument must be " "a callback object"))); return; } Local<Object> callbacks = Local<Object>::Cast (callbacks_value); if (!_gum_v8_callbacks_get (callbacks, "onMatch", &ctx.on_match, ctx.self->core)) { return; } if (!_gum_v8_callbacks_get (callbacks, "onComplete", &ctx.on_complete, ctx.self->core)) { return; } ctx.receiver = info.This (); gum_module_enumerate_ranges (*name_str, prot, gum_v8_module_handle_range_match, &ctx); ctx.on_complete->Call (ctx.receiver, 0, 0); }
/** * TJSオブジェクト用のメソッド * @param args 引数 * @return 結果 */ void TJSInstance::tjsInvoker(const FunctionCallbackInfo<Value>& args) { Isolate *isolate = args.GetIsolate(); HandleScope handle_scope(isolate); tTJSVariant instance; tTJSVariant method; if (getVariant(isolate, instance, args.This()) && getVariant(isolate, method, args.Data()->ToObject())) { FuncInfo info(instance, method, args); args.GetReturnValue().Set(info.exec()); return; } args.GetReturnValue().Set(ERROR_BADINSTANCE(isolate)); }
static void gum_v8_file_on_new_file (const FunctionCallbackInfo<Value> & info) { GumV8File * self = static_cast<GumV8File *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = self->core->isolate; if (!info.IsConstructCall ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Use `new File()` to create a new instance"))); return; } Local<Value> filename_val = info[0]; if (!filename_val->IsString ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "File: first argument must be a string specifying filename"))); return; } String::Utf8Value filename (filename_val); Local<Value> mode_val = info[1]; if (!mode_val->IsString ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "File: second argument must be a string specifying mode"))); return; } String::Utf8Value mode (mode_val); FILE * handle = fopen (*filename, *mode); if (handle == NULL) { gchar * message = g_strdup_printf ("File: failed to open file (%s)", strerror (errno)); isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, message))); g_free (message); return; } Local<Object> instance (info.Holder ()); GumFile * file = gum_file_new (instance, handle, self); instance->SetAlignedPointerInInternalField (0, file); }
/* * Prototype: * Process.enumerateMallocRanges(callback) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_process_on_enumerate_malloc_ranges ( const FunctionCallbackInfo<Value> & info) { GumV8MatchContext ctx; ctx.isolate = info.GetIsolate (); #ifdef HAVE_DARWIN ctx.self = static_cast<GumV8Process *> ( info.Data ().As<External> ()->Value ()); Local<Value> callbacks_value = info[0]; if (!callbacks_value->IsObject ()) { ctx.isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( ctx.isolate, "Process.enumerateMallocRanges: first argument must be " "a callback object"))); return; } Local<Object> callbacks = Local<Object>::Cast (callbacks_value); if (!_gum_v8_callbacks_get (callbacks, "onMatch", &ctx.on_match, ctx.self->core)) { return; } if (!_gum_v8_callbacks_get (callbacks, "onComplete", &ctx.on_complete, ctx.self->core)) { return; } ctx.receiver = info.This (); gum_process_enumerate_malloc_ranges (gum_v8_process_handle_malloc_range_match, &ctx); ctx.on_complete->Call (ctx.receiver, 0, 0); #else ctx.isolate->ThrowException (Exception::Error (String::NewFromUtf8 ( ctx.isolate, "Process.enumerateMallocRanges: not implemented yet for " GUM_SCRIPT_PLATFORM))); #endif }
static void gum_script_process_on_enumerate_ranges ( const FunctionCallbackInfo<Value> & info) { GumScriptMatchContext ctx; ctx.self = static_cast<GumScriptProcess *> ( info.Data ().As<External> ()->Value ()); ctx.isolate = info.GetIsolate (); GumPageProtection prot; if (!_gum_script_page_protection_get (info[0], &prot, ctx.self->core)) return; Local<Value> callbacks_value = info[1]; if (!callbacks_value->IsObject ()) { ctx.isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( ctx.isolate, "Process.enumerateRanges: second argument must be " "a callback object"))); return; } Local<Object> callbacks = Local<Object>::Cast (callbacks_value); if (!_gum_script_callbacks_get (callbacks, "onMatch", &ctx.on_match, ctx.self->core)) { return; } if (!_gum_script_callbacks_get (callbacks, "onComplete", &ctx.on_complete, ctx.self->core)) { return; } ctx.receiver = info.This (); gum_process_enumerate_ranges (prot, gum_script_process_handle_range_match, &ctx); ctx.on_complete->Call (ctx.receiver, 0, 0); return; }
void ModulePhysics::jsImpulse(const FunctionCallbackInfo<Value> &args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); ModulePhysics *module = (ModulePhysics*)HelperScript::Unwrap(args.Data()); if (args.Length() < 1 || !args[0]->IsString()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "first argument must be entity id as string"))); return; } uint64_t id = stoull(*String::Utf8Value(args[0])); if (!id) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "invalid entity id"))); return; } auto frm = module->Entity->Get<Form>(id); if (!frm) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "entity has no form property"))); return; } btVector3 impulse; if (args.Length() > 3) { if (!args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second, third and fourth arguments must be impulse values as numbers"))); return; } impulse = btVector3((float)args[1]->NumberValue(), (float)args[2]->NumberValue(), (float)args[3]->NumberValue()); } else if (args.Length() > 1) { if (!args[1]->IsNumber()) { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second argument must be a impulse as number"))); return; } impulse = btVector3(0, (float)args[1]->NumberValue(), 0); } else { isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "second or second, third and fourth arguments must be impulse values as numbers"))); return; } frm->Body->activate(); frm->Body->applyCentralImpulse(impulse); }
/* * Prototype: * Socket.peerAddress(socket_ptr) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_socket_on_peer_address (const FunctionCallbackInfo<Value> & info) { GumV8Socket * self = static_cast<GumV8Socket *> ( info.Data ().As<External> ()->Value ()); struct sockaddr_in6 large_addr; struct sockaddr * addr = reinterpret_cast<struct sockaddr *> (&large_addr); gum_socklen_t len = sizeof (large_addr); if (getpeername (info[0]->ToInteger ()->Value (), addr, &len) == 0) { info.GetReturnValue ().Set ( gum_v8_socket_address_to_value (addr, self->core)); } else { info.GetReturnValue ().SetNull (); } }
/* * Prototype: * Stalker.removeCallProbe(id) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_stalker_on_remove_call_probe ( const FunctionCallbackInfo<Value> & info) { GumV8Stalker * self = static_cast<GumV8Stalker *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); Local<Value> id = info[0]; if (!id->IsUint32 ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Stalker.removeCallProbe: argument must be a probe id"))); return; } gum_stalker_remove_call_probe (_gum_v8_stalker_get (self), id->ToUint32 ()->Value ()); return; }
void ConsoleInterfaces::Log(int type, const FunctionCallbackInfo<Value>& args) { Handle<External> ext = Handle<External>::Cast(args.Data()); Flathead *pFH = (Flathead *)ext->Value(); int counter = 0; if (pFH->GetConfiguration()->LoggingFn() != NULL) { for (int i = 0; i < args.Length(); i++) { Local<Value> value = args[i]; String::Utf8Value outputString(value); pFH->GetConfiguration()->LoggingFn()(type, *outputString); counter++; } } args.GetReturnValue().Set(counter); }
void FunctionTemplateProxy::InvocationCallbackProxy(const FunctionCallbackInfo<Value>& args) { auto proxy = static_cast<ProxyBase*>(args.Data().As<External>()->Value()); V8EngineProxy *engine; ManagedJSFunctionCallback callback; if (proxy->GetType() == FunctionTemplateProxyClass) { engine = static_cast<FunctionTemplateProxy*>(proxy)->_EngineProxy; callback = static_cast<FunctionTemplateProxy*>(proxy)->_ManagedCallback; } else if (proxy->GetType() == ObjectTemplateProxyClass) { engine = static_cast<ObjectTemplateProxy*>(proxy)->_EngineProxy; callback = static_cast<ObjectTemplateProxy*>(proxy)->_ManagedCallback; } else throw exception("'args.Data()' is not recognized."); if (callback != nullptr) // (note: '_ManagedCallback' may not be set on the proxy, and thus 'callback' may be null) { auto argLength = args.Length(); auto _args = argLength > 0 ? new HandleProxy*[argLength] : nullptr; for (auto i = 0; i < argLength; i++) _args[i] = engine->GetHandleProxy(args[i]); auto _this = engine->GetHandleProxy(args.Holder()); auto result = callback(0, args.IsConstructCall(), _this, _args, argLength); if (result != nullptr) if (result->IsError()) args.GetReturnValue().Set(ThrowException(Exception::Error(result->Handle()->ToString()))); else args.GetReturnValue().Set(result->Handle()); // (note: the returned value was created via p/invoke calls from the managed side, so the managed side is expected to tracked and free this handle when done) // (result == null == undefined [which means the managed side didn't return anything]) } }
/* * Prototype: * Process.setExceptionHandler(callback) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_process_on_set_exception_handler ( const FunctionCallbackInfo<Value> & info) { GumV8Process * self = static_cast<GumV8Process *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); bool argument_valid = false; Local<Function> callback; if (info.Length () >= 1) { Local<Value> argument = info[0]; if (argument->IsFunction ()) { argument_valid = true; callback = argument.As<Function> (); } else if (argument->IsNull ()) { argument_valid = true; } } if (!argument_valid) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "invalid argument"))); return; } gum_v8_exception_handler_free (self->exception_handler); self->exception_handler = NULL; if (!callback.IsEmpty ()) { self->exception_handler = gum_v8_exception_handler_new (callback, self->core); } }
void WeakRef::ConstructorCallback(const FunctionCallbackInfo<Value>& args) { try { auto extData = args.Data().As<External>(); auto thiz = reinterpret_cast<WeakRef*>(extData->Value()); thiz->ConstructorCallbackImpl(args); } catch (NativeScriptException& e) { e.ReThrowToV8(); } catch (std::exception e) { stringstream ss; ss << "Error: c++ exception: " << e.what() << endl; NativeScriptException nsEx(ss.str()); nsEx.ReThrowToV8(); } catch (...) { NativeScriptException nsEx(std::string("Error: c++ exception!")); nsEx.ReThrowToV8(); } }
/* * Prototype: * Stalker.unfollow(thread_id) * * Docs: * TBW * * Example: * TBW */ static void gum_v8_stalker_on_unfollow (const FunctionCallbackInfo<Value> & info) { GumV8Stalker * self = static_cast<GumV8Stalker *> ( info.Data ().As<External> ()->Value ()); GumStalker * stalker; GumThreadId thread_id; stalker = _gum_v8_stalker_get (self); if (info.Length () > 0) thread_id = info[0]->IntegerValue (); else thread_id = gum_process_get_current_thread_id (); if (thread_id == gum_process_get_current_thread_id ()) { self->pending_follow_level--; } else { gum_stalker_unfollow (stalker, thread_id); } }
/* * Prototype: * TBW * * Docs: * TBW * * Example: * TBW */ static void gum_v8_stalker_on_follow (const FunctionCallbackInfo<Value> & info) { GumV8Stalker * self = static_cast<GumV8Stalker *> ( info.Data ().As<External> ()->Value ()); GumV8Core * core = self->core; Isolate * isolate = info.GetIsolate (); GumThreadId thread_id; Local<Value> options_value; switch (info.Length ()) { case 0: thread_id = gum_process_get_current_thread_id (); break; case 1: if (info[0]->IsNumber ()) { thread_id = info[0]->IntegerValue (); } else { thread_id = gum_process_get_current_thread_id (); options_value = info[0]; } break; default: thread_id = info[0]->IntegerValue (); options_value = info[1]; break; } GumV8EventSinkOptions so; so.core = self->core; so.main_context = gum_script_scheduler_get_js_context (self->core->scheduler); so.event_mask = GUM_NOTHING; so.queue_capacity = self->queue_capacity; so.queue_drain_interval = self->queue_drain_interval; if (!options_value.IsEmpty ()) { if (!options_value->IsObject ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Stalker.follow: options argument must be an object"))); return; } Local<Object> options = Local<Object>::Cast (options_value); Local<String> events_key (String::NewFromUtf8 (isolate, "events")); if (options->Has (events_key)) { Local<Value> events_value (options->Get (events_key)); if (!events_value->IsObject ()) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Stalker.follow: events key must be an object"))); return; } Local<Object> events (Local<Object>::Cast (events_value)); if (gum_v8_flags_get (events, "call", core)) so.event_mask |= GUM_CALL; if (gum_v8_flags_get (events, "ret", core)) so.event_mask |= GUM_RET; if (gum_v8_flags_get (events, "exec", core)) so.event_mask |= GUM_EXEC; } if (so.event_mask != GUM_NOTHING && !_gum_v8_callbacks_get_opt (options, "onReceive", &so.on_receive, core)) { return; } if ((so.event_mask & GUM_CALL) != 0) { _gum_v8_callbacks_get_opt (options, "onCallSummary", &so.on_call_summary, core); } } if (self->sink != NULL) { GumEventSink * sink = self->sink; self->sink = NULL; g_object_unref (sink); } self->sink = gum_v8_event_sink_new (&so); if (thread_id == gum_process_get_current_thread_id ()) { self->pending_follow_level = 1; } else { GumEventSink * sink = self->sink; self->sink = NULL; gum_stalker_follow (_gum_v8_stalker_get (self), thread_id, sink); g_object_unref (sink); } }
/* * Prototype: * TBW * * Docs: * TBW * * Example: * TBW */ static void gum_script_thread_on_backtrace (const FunctionCallbackInfo<Value> & info) { GumScriptThread * self = static_cast<GumScriptThread *> ( info.Data ().As<External> ()->Value ()); Isolate * isolate = info.GetIsolate (); int num_args = info.Length (); GumCpuContext * cpu_context = NULL; if (num_args >= 1) { Local<Value> value = info[0]; if (!value->IsNull ()) { if (!_gum_script_cpu_context_get (value, &cpu_context, self->core)) return; } } bool accurate = true; if (num_args >= 2) { Local<Value> selector = info[1]; if (!selector->IsNull ()) { if ((*self->fuzzy_enum_value) == selector) { accurate = false; } else if ((*self->accurate_enum_value) != selector) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, "Thread.backtrace: invalid backtracer enum value"))); return; } } } GumBacktracer * backtracer; if (accurate) { if (self->accurate_backtracer == NULL) self->accurate_backtracer = gum_backtracer_make_accurate (); backtracer = self->accurate_backtracer; } else { if (self->fuzzy_backtracer == NULL) self->fuzzy_backtracer = gum_backtracer_make_fuzzy (); backtracer = self->fuzzy_backtracer; } if (backtracer == NULL) { isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 ( isolate, accurate ? "Thread.backtrace: backtracer not yet available for this " "platform; please try Thread.backtrace(context, Backtracer.FUZZY)" : "Thread.backtrace: backtracer not yet available for this " "platform; please try Thread.backtrace(context, Backtracer.ACCURATE)" ))); return; } GumReturnAddressArray ret_addrs; gum_backtracer_generate (backtracer, cpu_context, &ret_addrs); Local<Array> result = Array::New (isolate, ret_addrs.len); for (guint i = 0; i != ret_addrs.len; i++) result->Set (i, _gum_script_pointer_new (ret_addrs.items[i], self->core)); info.GetReturnValue ().Set (result); }