xref: /haiku/src/bin/debug/strace/exec.cpp (revision 899e0ef82b5624ace2ccfa5f5a58c8ebee54aaef)
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 
17 using BPrivate::AutoDeleter;
18 
19 
20 class FlatArgsTypeHandler : public TypeHandler {
21 public:
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 
106 void
107 patch_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