root/src/bin/debug/strace/area.cpp
/*
 * 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));
}