README.md
Rendering markdown...
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index fed771af2a4..75038a0d348 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -95,6 +95,165 @@
namespace v8 {
namespace internal {
+namespace PoCHelper {
+#include <Windows.h>
+
+Handle<FunctionTemplateInfo> NewFunctionTemplate(
+ Isolate* isolate, FunctionCallback func,
+ ConstructorBehavior constructor_behavior) {
+ // Use the API functions here as they are more convenient to use.
+ v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+ Local<FunctionTemplate> function_template =
+ FunctionTemplate::New(api_isolate, func, {}, {}, 0, constructor_behavior,
+ SideEffectType::kHasSideEffect);
+ return v8::Utils::OpenHandle(*function_template);
+}
+
+Handle<JSFunction> CreateFunc(Isolate* isolate, FunctionCallback func,
+ Handle<String> name, bool is_constructor) {
+ ConstructorBehavior constructor_behavior = is_constructor
+ ? ConstructorBehavior::kAllow
+ : ConstructorBehavior::kThrow;
+ Handle<FunctionTemplateInfo> function_template =
+ NewFunctionTemplate(isolate, func, constructor_behavior);
+ return ApiNatives::InstantiateFunction(isolate, function_template, name)
+ .ToHandleChecked();
+}
+
+void InstallFunc(Isolate* isolate, Handle<JSObject> holder,
+ FunctionCallback func, const char* name, int num_parameters,
+ bool is_constructor) {
+ Factory* factory = isolate->factory();
+ Handle<String> function_name = factory->NewStringFromAsciiChecked(name);
+ Handle<JSFunction> function =
+ CreateFunc(isolate, func, function_name, is_constructor);
+ function->shared()->set_length(num_parameters);
+ JSObject::AddProperty(isolate, holder, function_name, function, NONE);
+}
+
+void InstallFunction(Isolate* isolate, Handle<JSObject> holder,
+ FunctionCallback func, const char* name,
+ int num_parameters) {
+ InstallFunc(isolate, holder, func, name, num_parameters, false);
+}
+
+void GetBaseOf(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ DCHECK(ValidateCallbackInfo(info));
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<v8::Context> context = isolate->GetCurrentContext();
+
+ if (!info[0]->IsString()) {
+ isolate->ThrowError("First argument must be a string");
+ return;
+ }
+
+ v8::String::Utf8Value field_name(isolate, info[0]);
+ auto baseAddress = (intptr_t)GetModuleHandleA(*field_name);
+ info.GetReturnValue().Set(v8::BigInt::New(isolate, baseAddress));
+}
+
+void ReadBits(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ DCHECK(ValidateCallbackInfo(info));
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<v8::Context> context = isolate->GetCurrentContext();
+
+ if (!info[0]->IsBigInt()) {
+ isolate->ThrowError("First argument must be a BigInt");
+ return;
+ }
+
+ if (!info[1]->IsInt32()) {
+ isolate->ThrowError("Second argument must be a number");
+ return;
+ }
+
+ Local<v8::BigInt> bigint = info[0].As<v8::BigInt>();
+ const auto bits = info[1]->Int32Value(context).FromMaybe(64);
+
+ uint64_t address = bigint->Uint64Value();
+ Local<v8::BigInt> value = v8::BigInt::NewFromUnsigned(isolate, 0);
+ switch (bits) {
+ case 8:
+ value = v8::BigInt::NewFromUnsigned(isolate, *(uint8_t*)address);
+ break;
+ case 16:
+ value = v8::BigInt::NewFromUnsigned(isolate, *(uint16_t*)address);
+ break;
+ case 32:
+ value = v8::BigInt::NewFromUnsigned(isolate, *(uint32_t*)address);
+ break;
+ case 64:
+ value = v8::BigInt::NewFromUnsigned(isolate, *(uint64_t*)address);
+ break;
+ default:
+ isolate->ThrowError("Second argument must be one of 8, 16, 32, 64");
+ return;
+ }
+
+ info.GetReturnValue().Set(value);
+}
+
+void WriteBits(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ DCHECK(ValidateCallbackInfo(info));
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<v8::Context> context = isolate->GetCurrentContext();
+
+ if (!info[0]->IsBigInt()) {
+ isolate->ThrowError("First argument must be a BigInt");
+ return;
+ }
+
+ if (!info[1]->IsBigInt()) {
+ isolate->ThrowError("Second argument must be a BigInt");
+ return;
+ }
+
+ if (!info[2]->IsInt32()) {
+ isolate->ThrowError("Third argument must be a number");
+ return;
+ }
+ const auto bits = info[2]->Int32Value(context).FromMaybe(64);
+
+ Local<v8::BigInt> bigint_address = info[0].As<v8::BigInt>();
+ Local<v8::BigInt> bigint_value = info[1].As<v8::BigInt>();
+
+ uint64_t address = bigint_address->Uint64Value();
+ Local<v8::BigInt> value = v8::BigInt::NewFromUnsigned(isolate, 0);
+ switch (bits) {
+ case 8:
+ *(uint8_t*)address = (uint8_t)bigint_value->Uint64Value();
+ break;
+ case 16:
+ *(uint16_t*)address = (uint16_t)bigint_value->Uint64Value();
+ break;
+ case 32:
+ *(uint32_t*)address = (uint32_t)bigint_value->Uint64Value();
+ break;
+ case 64:
+ *(uint64_t*)address = bigint_value->Uint64Value();
+ break;
+ default:
+ isolate->ThrowError("Second argument must be one of 8, 16, 32, 64");
+ return;
+ }
+}
+
+void Install(Isolate* isolate) {
+ Handle<JSObject> helper = isolate->factory()->NewJSObject(
+ isolate->object_function(), AllocationType::kOld);
+
+ InstallFunction(isolate, helper, GetBaseOf, "getBaseOf", 1);
+ InstallFunction(isolate, helper, ReadBits, "readBits", 2);
+ InstallFunction(isolate, helper, WriteBits, "writeBits", 3);
+
+ // Install the helper object as property on the global object.
+ Handle<JSGlobalObject> global = isolate->global_object();
+ Handle<String> name =
+ isolate->factory()->NewStringFromAsciiChecked("POCHelper");
+ JSObject::AddProperty(isolate, global, name, helper, DONT_ENUM);
+}
+} // namespace PoCHelper
+
void SourceCodeCache::Initialize(Isolate* isolate, bool create_heap_objects) {
cache_ = create_heap_objects ? ReadOnlyRoots(isolate).empty_fixed_array()
: Tagged<FixedArray>();
@@ -6505,6 +6664,8 @@ bool Genesis::InstallSpecialObjects(
JSObject::AddProperty(isolate, Error, name, stack_trace_limit, NONE);
}
+ PoCHelper::Install(isolate);
+
#if V8_ENABLE_WEBASSEMBLY
WasmJs::Install(isolate);
#endif // V8_ENABLE_WEBASSEMBLY