xref: /haiku/src/bin/debug/strace/mutex.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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:
45 	MutexTypeHandler()
46 		:
47 		FlagsTypeHandler(kMutexFlags)
48 	{
49 	}
50 
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 
72 	string GetReturnValue(Context &context, uint64 value)
73 	{
74 		return context.FormatPointer((void *)value);
75 	}
76 };
77 
78 
79 void
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