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