⛏️ index : haiku.git

/*
 * Copyright 2023, Haiku Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */


#include <OS.h>
#include <vm_defs.h>

#include "strace.h"
#include "Syscall.h"
#include "TypeHandler.h"


#define FLAG_INFO_ENTRY(name) \
	{ name, #name }

static const FlagsTypeHandler::FlagInfo kAreaProtectionFlagInfos[] = {
	FLAG_INFO_ENTRY(B_READ_AREA),
	FLAG_INFO_ENTRY(B_WRITE_AREA),
	FLAG_INFO_ENTRY(B_EXECUTE_AREA),
	FLAG_INFO_ENTRY(B_STACK_AREA),

	FLAG_INFO_ENTRY(B_CLONEABLE_AREA),
	FLAG_INFO_ENTRY(B_OVERCOMMITTING_AREA),

	{ 0, NULL }
};


struct enum_info {
	unsigned int index;
	const char *name;
};

#define ENUM_INFO_ENTRY(name) \
	{ name, #name }

static const enum_info kAddressSpecs[] = {
	ENUM_INFO_ENTRY(B_ANY_ADDRESS),
	ENUM_INFO_ENTRY(B_EXACT_ADDRESS),
	ENUM_INFO_ENTRY(B_BASE_ADDRESS),
	ENUM_INFO_ENTRY(B_CLONE_ADDRESS),
	ENUM_INFO_ENTRY(B_ANY_KERNEL_ADDRESS),
	ENUM_INFO_ENTRY(B_RANDOMIZED_ANY_ADDRESS),
	ENUM_INFO_ENTRY(B_RANDOMIZED_BASE_ADDRESS),

	{ 0, NULL }
};


static const enum_info kAreaMappings[] = {
	ENUM_INFO_ENTRY(REGION_NO_PRIVATE_MAP),
	ENUM_INFO_ENTRY(REGION_PRIVATE_MAP),

	{ 0, NULL }
};

static FlagsTypeHandler::FlagsList kAreaProtectionFlags;
static EnumTypeHandler::EnumMap kAddressSpecsMap;
static EnumTypeHandler::EnumMap kAreaMappingMap;


void
patch_area()
{
	for (int i = 0; kAreaProtectionFlagInfos[i].name != NULL; i++) {
		kAreaProtectionFlags.push_back(kAreaProtectionFlagInfos[i]);
	}
	for (int i = 0; kAddressSpecs[i].name != NULL; i++) {
		kAddressSpecsMap[kAddressSpecs[i].index] = kAddressSpecs[i].name;
	}
	for (int i = 0; kAreaMappings[i].name != NULL; i++) {
		kAreaMappingMap[kAreaMappings[i].index] = kAreaMappings[i].name;
	}

	Syscall *create = get_syscall("_kern_create_area");
	create->GetParameter("address")->SetInOut(true);
	create->GetParameter("addressSpec")->SetHandler(
		new EnumTypeHandler(kAddressSpecsMap));
	create->GetParameter("protection")->SetHandler(
		new FlagsTypeHandler(kAreaProtectionFlags));

	Syscall *transfer = get_syscall("_kern_transfer_area");
	transfer->GetParameter("_address")->SetInOut(true);
	transfer->GetParameter("addressSpec")->SetHandler(
		new EnumTypeHandler(kAddressSpecsMap));

	Syscall *clone = get_syscall("_kern_clone_area");
	clone->GetParameter("_address")->SetInOut(true);
	clone->GetParameter("addressSpec")->SetHandler(
		new EnumTypeHandler(kAddressSpecsMap));
	clone->GetParameter("protection")->SetHandler(
		new FlagsTypeHandler(kAreaProtectionFlags));

	Syscall *reserve_address_range = get_syscall("_kern_reserve_address_range");
	reserve_address_range->GetParameter("_address")->SetInOut(true);
	reserve_address_range->GetParameter("addressSpec")->SetHandler(
		new EnumTypeHandler(kAddressSpecsMap));

	Syscall *set_area_protection = get_syscall("_kern_set_area_protection");
	set_area_protection->GetParameter("newProtection")->SetHandler(
		new FlagsTypeHandler(kAreaProtectionFlags));

	Syscall *map_file = get_syscall("_kern_map_file");
	map_file->GetParameter("address")->SetInOut(true);
	map_file->GetParameter("addressSpec")->SetHandler(
		new EnumTypeHandler(kAddressSpecsMap));
	map_file->GetParameter("protection")->SetHandler(
		new FlagsTypeHandler(kAreaProtectionFlags));
	map_file->GetParameter("mapping")->SetHandler(
		new EnumTypeHandler(kAreaMappingMap));

	Syscall *set_memory_protection = get_syscall("_kern_set_memory_protection");
	set_memory_protection->GetParameter("protection")->SetHandler(
		new FlagsTypeHandler(kAreaProtectionFlags));
}