1/*
2 * Copyright 2023, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <OS.h>
8#include <vm_defs.h>
9
10#include "strace.h"
11#include "Syscall.h"
12#include "TypeHandler.h"
13
14
15#define FLAG_INFO_ENTRY(name) \
16	{ name, #name }
17
18static const FlagsTypeHandler::FlagInfo kAreaProtectionFlagInfos[] = {
19	FLAG_INFO_ENTRY(B_READ_AREA),
20	FLAG_INFO_ENTRY(B_WRITE_AREA),
21	FLAG_INFO_ENTRY(B_EXECUTE_AREA),
22	FLAG_INFO_ENTRY(B_STACK_AREA),
23
24	FLAG_INFO_ENTRY(B_CLONEABLE_AREA),
25	FLAG_INFO_ENTRY(B_OVERCOMMITTING_AREA),
26
27	{ 0, NULL }
28};
29
30
31struct enum_info {
32	unsigned int index;
33	const char *name;
34};
35
36#define ENUM_INFO_ENTRY(name) \
37	{ name, #name }
38
39static const enum_info kAddressSpecs[] = {
40	ENUM_INFO_ENTRY(B_ANY_ADDRESS),
41	ENUM_INFO_ENTRY(B_EXACT_ADDRESS),
42	ENUM_INFO_ENTRY(B_BASE_ADDRESS),
43	ENUM_INFO_ENTRY(B_CLONE_ADDRESS),
44	ENUM_INFO_ENTRY(B_ANY_KERNEL_ADDRESS),
45	ENUM_INFO_ENTRY(B_RANDOMIZED_ANY_ADDRESS),
46	ENUM_INFO_ENTRY(B_RANDOMIZED_BASE_ADDRESS),
47
48	{ 0, NULL }
49};
50
51
52static FlagsTypeHandler::FlagsList kAreaProtectionFlags;
53static EnumTypeHandler::EnumMap kAddressSpecsMap;
54
55
56void
57patch_area()
58{
59	for (int i = 0; kAreaProtectionFlagInfos[i].name != NULL; i++) {
60		kAreaProtectionFlags.push_back(kAreaProtectionFlagInfos[i]);
61	}
62	for (int i = 0; kAddressSpecs[i].name != NULL; i++) {
63		kAddressSpecsMap[kAddressSpecs[i].index] = kAddressSpecs[i].name;
64	}
65
66	Syscall *create = get_syscall("_kern_create_area");
67	create->GetParameter("address")->SetInOut(true);
68	create->GetParameter("addressSpec")->SetHandler(
69		new EnumTypeHandler(kAddressSpecsMap));
70	create->GetParameter("protection")->SetHandler(
71		new FlagsTypeHandler(kAreaProtectionFlags));
72
73	Syscall *transfer = get_syscall("_kern_transfer_area");
74	transfer->GetParameter("_address")->SetInOut(true);
75	transfer->GetParameter("addressSpec")->SetHandler(
76		new EnumTypeHandler(kAddressSpecsMap));
77
78	Syscall *clone = get_syscall("_kern_clone_area");
79	clone->GetParameter("_address")->SetInOut(true);
80	clone->GetParameter("addressSpec")->SetHandler(
81		new EnumTypeHandler(kAddressSpecsMap));
82	clone->GetParameter("protection")->SetHandler(
83		new FlagsTypeHandler(kAreaProtectionFlags));
84
85	Syscall *reserve_address_range = get_syscall("_kern_reserve_address_range");
86	reserve_address_range->GetParameter("_address")->SetInOut(true);
87	reserve_address_range->GetParameter("addressSpec")->SetHandler(
88		new EnumTypeHandler(kAddressSpecsMap));
89
90	Syscall *set_area_protection = get_syscall("_kern_set_area_protection");
91	set_area_protection->GetParameter("newProtection")->SetHandler(
92		new FlagsTypeHandler(kAreaProtectionFlags));
93
94	Syscall *map_file = get_syscall("_kern_map_file");
95	map_file->GetParameter("address")->SetInOut(true);
96	map_file->GetParameter("addressSpec")->SetHandler(
97		new EnumTypeHandler(kAddressSpecsMap));
98	map_file->GetParameter("protection")->SetHandler(
99		new FlagsTypeHandler(kAreaProtectionFlags));
100
101	Syscall *set_memory_protection = get_syscall("_kern_set_memory_protection");
102	set_memory_protection->GetParameter("protection")->SetHandler(
103		new FlagsTypeHandler(kAreaProtectionFlags));
104}
105