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
20static 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
28static FlagsTypeHandler::FlagsList kMutexFlags;
29
30
31class MutexTypeHandler : public FlagsTypeHandler {
32public:
33    MutexTypeHandler()
34        :
35        FlagsTypeHandler(kMutexFlags)
36    {
37    }
38
39	string GetParameterValue(Context &context, Parameter *param,
40		const void *address)
41	{
42        void *data = *(void **)address;
43
44		if (context.GetContents(Context::POINTER_VALUES)) {
45            int32 value, bytesRead;
46            status_t err = context.Reader().Read(data, &value, sizeof(value), bytesRead);
47            if (err != B_OK)
48                return context.FormatPointer(data);
49
50            string r = context.FormatPointer(data);
51            r += " [";
52            r += RenderValue(context, (unsigned int)value);
53            r += "]";
54            return r;
55        }
56
57		return context.FormatPointer(data);
58	}
59
60	string GetReturnValue(Context &context, uint64 value)
61	{
62		return context.FormatPointer((void *)value);
63	}
64};
65
66
67void
68patch_mutex()
69{
70    for (int i = 0; kMutexFlagsInfo[i].name != NULL; i++) {
71        kMutexFlags.push_back(kMutexFlagsInfo[i]);
72    }
73
74    Syscall *mutex_lock = get_syscall("_kern_mutex_lock");
75    mutex_lock->GetParameter("mutex")->SetHandler(new MutexTypeHandler());
76
77    Syscall *mutex_unlock = get_syscall("_kern_mutex_unblock");
78    mutex_unlock->GetParameter("mutex")->SetHandler(new MutexTypeHandler());
79
80    Syscall *mutex_switch_lock = get_syscall("_kern_mutex_switch_lock");
81    mutex_switch_lock->GetParameter("fromMutex")->SetHandler(new MutexTypeHandler());
82    mutex_switch_lock->GetParameter("toMutex")->SetHandler(new MutexTypeHandler());
83}
84