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 <user_mutex_defs.h>
10
11 #include "strace.h"
12 #include "Context.h"
13 #include "MemoryReader.h"
14 #include "TypeHandler.h"
15
16
17 #define FLAG_INFO_ENTRY(name) \
18 { name, #name }
19
20 static const FlagsTypeHandler::FlagInfo kMutexFlagsInfo[] = {
21 FLAG_INFO_ENTRY(B_USER_MUTEX_LOCKED),
22 FLAG_INFO_ENTRY(B_USER_MUTEX_WAITING),
23 FLAG_INFO_ENTRY(B_USER_MUTEX_DISABLED),
24
25 { 0, NULL }
26 };
27
28 static const FlagsTypeHandler::FlagInfo kMutexOptionFlagsInfo[] = {
29 FLAG_INFO_ENTRY(B_RELATIVE_TIMEOUT),
30 FLAG_INFO_ENTRY(B_ABSOLUTE_TIMEOUT),
31 FLAG_INFO_ENTRY(B_TIMEOUT_REAL_TIME_BASE),
32
33 FLAG_INFO_ENTRY(B_USER_MUTEX_SHARED),
34 FLAG_INFO_ENTRY(B_USER_MUTEX_UNBLOCK_ALL),
35
36 { 0, NULL }
37 };
38
39 static FlagsTypeHandler::FlagsList kMutexFlags;
40 static FlagsTypeHandler::FlagsList kMutexOptionFlags;
41
42
43 class MutexTypeHandler : public FlagsTypeHandler {
44 public:
MutexTypeHandler()45 MutexTypeHandler()
46 :
47 FlagsTypeHandler(kMutexFlags)
48 {
49 }
50
GetParameterValue(Context & context,Parameter * param,const void * address)51 string GetParameterValue(Context &context, Parameter *param,
52 const void *address)
53 {
54 void *data = *(void **)address;
55
56 if (context.GetContents(Context::POINTER_VALUES)) {
57 int32 value, bytesRead;
58 status_t err = context.Reader().Read(data, &value, sizeof(value), bytesRead);
59 if (err != B_OK)
60 return context.FormatPointer(data);
61
62 string r = context.FormatPointer(data);
63 r += " [";
64 r += RenderValue(context, (unsigned int)value);
65 r += "]";
66 return r;
67 }
68
69 return context.FormatPointer(data);
70 }
71
GetReturnValue(Context & context,uint64 value)72 string GetReturnValue(Context &context, uint64 value)
73 {
74 return context.FormatPointer((void *)value);
75 }
76 };
77
78
79 void
patch_mutex()80 patch_mutex()
81 {
82 for (int i = 0; kMutexFlagsInfo[i].name != NULL; i++)
83 kMutexFlags.push_back(kMutexFlagsInfo[i]);
84 for (int i = 0; kMutexOptionFlagsInfo[i].name != NULL; i++)
85 kMutexOptionFlags.push_back(kMutexOptionFlagsInfo[i]);
86
87 Syscall *mutex_lock = get_syscall("_kern_mutex_lock");
88 mutex_lock->GetParameter("mutex")->SetHandler(new MutexTypeHandler());
89 mutex_lock->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kMutexOptionFlags));
90
91 Syscall *mutex_unlock = get_syscall("_kern_mutex_unblock");
92 mutex_unlock->GetParameter("mutex")->SetHandler(new MutexTypeHandler());
93 mutex_unlock->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kMutexOptionFlags));
94
95 Syscall *mutex_switch_lock = get_syscall("_kern_mutex_switch_lock");
96 mutex_switch_lock->GetParameter("fromMutex")->SetHandler(new MutexTypeHandler());
97 mutex_switch_lock->GetParameter("fromFlags")->SetHandler(
98 new FlagsTypeHandler(kMutexOptionFlags));
99 mutex_switch_lock->GetParameter("toMutex")->SetHandler(new MutexTypeHandler());
100 mutex_switch_lock->GetParameter("toFlags")->SetHandler(
101 new FlagsTypeHandler(kMutexOptionFlags));
102
103 Syscall *mutex_sem_acquire = get_syscall("_kern_mutex_sem_acquire");
104 mutex_sem_acquire->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kMutexOptionFlags));
105
106 Syscall *mutex_sem_release = get_syscall("_kern_mutex_sem_release");
107 mutex_sem_release->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kMutexOptionFlags));
108 }
109