1/*
2 * Copyright 2023, Trung Nguyen, trungnt282910@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <string.h>
8
9#include <AutoDeleter.h>
10
11#include "strace.h"
12#include "Context.h"
13#include "MemoryReader.h"
14#include "TypeHandler.h"
15
16
17using BPrivate::AutoDeleter;
18
19
20class FlatArgsTypeHandler : public TypeHandler {
21public:
22	string GetParameterValue(Context &context, Parameter *param,
23		const void *address)
24	{
25		size_t flatArgsSize;
26		int32 argCount, envCount;
27		char *flatArgs, *flatArgsEnd;
28		int32 bytesRead;
29		status_t err;
30		ArrayDeleter<char> flatArgsDeleter;
31		string r;
32
33		if (!context.GetContents(Context::COMPLEX_STRUCTS))
34			goto fallback;
35
36		param = context.GetNextSibling(param);
37		if (param == NULL)
38			goto fallback;
39		flatArgsSize = context.ReadValue<size_t>(param);
40
41		param = context.GetNextSibling(param);
42		if (param == NULL)
43			goto fallback;
44		argCount = context.ReadValue<int32>(param);
45
46		param = context.GetNextSibling(param);
47		if (param == NULL)
48			goto fallback;
49		envCount = context.ReadValue<int32>(param);
50
51		flatArgs = new (std::nothrow) char[flatArgsSize + 1];
52		if (flatArgs == NULL)
53			goto fallback;
54
55		flatArgsDeleter.SetTo(flatArgs);
56
57		// Guard with a null byte to prevent faulty buffers.
58		flatArgsEnd = flatArgs + flatArgsSize;
59		*flatArgsEnd = '\0';
60
61		err = context.Reader().Read(*(void **)address, flatArgs, flatArgsSize,
62			bytesRead);
63		if (err != B_OK)
64			goto fallback;
65
66		flatArgs += sizeof(void *) * (argCount + envCount + 2);
67
68		r = "{args = [";
69
70		for (int32 i = 0; i < argCount && flatArgs < flatArgsEnd; i++) {
71			if (i > 0)
72				r += ", ";
73			size_t currentLen = strlen(flatArgs);
74			r += "\"";
75			r += flatArgs;
76			r += "\"";
77			flatArgs += currentLen + 1;
78		}
79
80		r += "], env = [";
81
82		for (int32 i = 0; i < envCount && flatArgs < flatArgsEnd; i++) {
83			if (i > 0)
84				r += ", ";
85			size_t currentLen = strlen(flatArgs);
86			r += "\"";
87			r += flatArgs;
88			r += "\"";
89			flatArgs += currentLen + 1;
90		}
91
92		r += "]}";
93
94		return r;
95	fallback:
96		return context.FormatPointer(address);
97	}
98
99	string GetReturnValue(Context &context, uint64 value)
100	{
101		return context.FormatPointer((void *)value);
102	}
103};
104
105
106void
107patch_exec()
108{
109	Syscall *exec = get_syscall("_kern_exec");
110	exec->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler());
111
112	Syscall *load_image = get_syscall("_kern_load_image");
113	load_image->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler());
114}
115