1 /* 2 * Copyright 2023-2024, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <OS.h> 8 #include <poll.h> 9 10 #include <event_queue_defs.h> 11 12 #include "strace.h" 13 #include "Syscall.h" 14 #include "Context.h" 15 #include "MemoryReader.h" 16 #include "TypeHandler.h" 17 18 19 // #pragma mark - enums & flags handlers 20 21 22 struct enum_info { 23 unsigned int index; 24 const char *name; 25 }; 26 27 #define ENUM_INFO_ENTRY(name) \ 28 { name, #name } 29 30 31 #define FLAG_INFO_ENTRY(name) \ 32 { name, #name } 33 34 35 static const FlagsTypeHandler::FlagInfo kPollFlagInfos[] = { 36 FLAG_INFO_ENTRY(POLLIN), 37 FLAG_INFO_ENTRY(POLLOUT), 38 FLAG_INFO_ENTRY(POLLRDBAND), 39 FLAG_INFO_ENTRY(POLLWRBAND), 40 FLAG_INFO_ENTRY(POLLPRI), 41 42 FLAG_INFO_ENTRY(POLLERR), 43 FLAG_INFO_ENTRY(POLLHUP), 44 FLAG_INFO_ENTRY(POLLNVAL), 45 46 { 0, NULL } 47 }; 48 49 50 static const FlagsTypeHandler::FlagInfo kEventFlagInfos[] = { 51 FLAG_INFO_ENTRY(B_EVENT_READ), 52 FLAG_INFO_ENTRY(B_EVENT_WRITE), 53 FLAG_INFO_ENTRY(B_EVENT_ERROR), 54 FLAG_INFO_ENTRY(B_EVENT_PRIORITY_READ), 55 FLAG_INFO_ENTRY(B_EVENT_PRIORITY_WRITE), 56 FLAG_INFO_ENTRY(B_EVENT_HIGH_PRIORITY_READ), 57 FLAG_INFO_ENTRY(B_EVENT_HIGH_PRIORITY_WRITE), 58 FLAG_INFO_ENTRY(B_EVENT_DISCONNECTED), 59 FLAG_INFO_ENTRY(B_EVENT_INVALID), 60 61 /* event queue only */ 62 FLAG_INFO_ENTRY(B_EVENT_LEVEL_TRIGGERED), 63 FLAG_INFO_ENTRY(B_EVENT_ONE_SHOT), 64 65 { 0, NULL } 66 }; 67 68 69 static const char* kObjectTypes[] = { 70 "fd", 71 "sem", 72 "port", 73 "thread", 74 }; 75 76 77 static FlagsTypeHandler::FlagsList kPollFlags; 78 static FlagsTypeHandler sPollFlagsHandler(kPollFlags); 79 static FlagsTypeHandler::FlagsList kEventFlags; 80 static FlagsTypeHandler sEventFlagsHandler(kEventFlags); 81 82 83 // #pragma mark - specialized type handlers 84 85 86 static string 87 read_fdset(Context &context, void *data) 88 { 89 // default FD_SETSIZE is 1024 90 unsigned long tmp[1024 / (sizeof(unsigned long) * 8)]; 91 int32 bytesRead; 92 93 status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); 94 if (err != B_OK) 95 return context.FormatPointer(data); 96 97 /* implicitly align to unsigned long lower boundary */ 98 int count = bytesRead / sizeof(unsigned long); 99 int added = 0; 100 101 string r; 102 r.reserve(16); 103 104 r = "["; 105 106 for (int i = 0; i < count && added < 8; i++) { 107 for (int j = 0; 108 j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) { 109 if (tmp[i] & (1UL << j)) { 110 if (added > 0) 111 r += " "; 112 unsigned int fd = i * sizeof(unsigned long) * 8 + j; 113 r += context.FormatUnsigned(fd); 114 added++; 115 } 116 } 117 } 118 119 if (added >= 8) 120 r += " ..."; 121 122 r += "]"; 123 124 return r; 125 } 126 127 128 template<> 129 string 130 TypeHandlerImpl<fd_set *>::GetParameterValue(Context &context, Parameter *, 131 const void *address) 132 { 133 void *data = *(void **)address; 134 if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) 135 return read_fdset(context, data); 136 return context.FormatPointer(data); 137 } 138 139 140 template<> 141 string 142 TypeHandlerImpl<fd_set *>::GetReturnValue(Context &context, uint64 value) 143 { 144 return context.FormatPointer((void *)value); 145 } 146 147 148 static string 149 read_pollfd(Context &context, void *data) 150 { 151 nfds_t numfds = context.ReadValue<nfds_t>(context.GetSibling(1)); 152 if ((int64)numfds <= 0) 153 return string(); 154 155 pollfd tmp[numfds]; 156 int32 bytesRead; 157 158 status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); 159 if (err != B_OK) 160 return context.FormatPointer(data); 161 162 string r; 163 r.reserve(16); 164 165 r = "["; 166 167 int added = 0; 168 for (nfds_t i = 0; i < numfds && added < 8; i++) { 169 if ((tmp[i].fd == -1 || tmp[i].revents == 0) 170 && context.GetContents(Context::OUTPUT_VALUES)) { 171 continue; 172 } 173 if (added > 0) 174 r += ", "; 175 r += "{fd=" + context.FormatSigned(tmp[i].fd); 176 if (tmp[i].fd != -1 && context.GetContents(Context::INPUT_VALUES)) { 177 r += ", events="; 178 r += sPollFlagsHandler.RenderValue(context, tmp[i].events); 179 } 180 if (context.GetContents(Context::OUTPUT_VALUES)) { 181 r += ", revents="; 182 r += sPollFlagsHandler.RenderValue(context, tmp[i].revents); 183 } 184 added++; 185 r += "}"; 186 } 187 188 if (added >= 8) 189 r += " ..."; 190 191 r += "]"; 192 return r; 193 } 194 195 196 template<> 197 string 198 TypeHandlerImpl<pollfd *>::GetParameterValue(Context &context, Parameter *, 199 const void *address) 200 { 201 void *data = *(void **)address; 202 if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) 203 return read_pollfd(context, data); 204 return context.FormatPointer(data); 205 } 206 207 208 template<> 209 string 210 TypeHandlerImpl<pollfd *>::GetReturnValue(Context &context, uint64 value) 211 { 212 return context.FormatPointer((void *)value); 213 } 214 215 216 static string 217 read_object_wait_infos(Context &context, Parameter *param, void *data) 218 { 219 int numInfos = context.ReadValue<int>(context.GetNextSibling(param)); 220 if (numInfos <= 0) 221 return string(); 222 223 object_wait_info tmp[numInfos]; 224 int32 bytesRead; 225 226 status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); 227 if (err != B_OK) 228 return context.FormatPointer(data); 229 230 string r; 231 r.reserve(16); 232 233 r = "["; 234 235 for (int i = 0; i < numInfos; i++) { 236 if (i > 0) 237 r += ", "; 238 if (i >= 8) { 239 r += "..."; 240 break; 241 } 242 243 r += "{"; 244 r += (tmp[i].type < sizeof(kObjectTypes)) ? 245 kObjectTypes[tmp[i].type] : context.FormatUnsigned(tmp[i].type); 246 r += "="; 247 r += context.FormatSigned(tmp[i].object); 248 249 r += ", events="; 250 r += sEventFlagsHandler.RenderValue(context, tmp[i].events); 251 r += "}"; 252 } 253 254 r += "]"; 255 return r; 256 } 257 258 259 template<> 260 string 261 TypeHandlerImpl<object_wait_info *>::GetParameterValue(Context &context, Parameter *param, 262 const void *address) 263 { 264 void *data = *(void **)address; 265 if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) 266 return read_object_wait_infos(context, param, data); 267 return context.FormatPointer(data); 268 } 269 270 271 template<> 272 string 273 TypeHandlerImpl<object_wait_info *>::GetReturnValue(Context &context, uint64 value) 274 { 275 return context.FormatPointer((void *)value); 276 } 277 278 279 static string 280 read_event_wait_infos(Context &context, Parameter *param, void *data) 281 { 282 int numInfos = 0; 283 if (param->Out()) 284 numInfos = context.GetReturnValue(); 285 else 286 numInfos = context.ReadValue<int>(context.GetNextSibling(param)); 287 if (numInfos <= 0) 288 return context.FormatPointer(data); 289 290 event_wait_info tmp[numInfos]; 291 int32 bytesRead; 292 293 status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); 294 if (err != B_OK) 295 return context.FormatPointer(data); 296 297 string r; 298 r.reserve(16); 299 300 r = "["; 301 302 for (int i = 0; i < numInfos; i++) { 303 if (i > 0) 304 r += ", "; 305 if (i >= 8) { 306 r += "..."; 307 break; 308 } 309 310 r += "{"; 311 r += (tmp[i].type < sizeof(kObjectTypes)) ? 312 kObjectTypes[tmp[i].type] : context.FormatUnsigned(tmp[i].type); 313 r += "="; 314 r += context.FormatSigned(tmp[i].object); 315 316 r += ", events="; 317 if (tmp[i].events == -1) 318 r += "-1"; 319 else if (tmp[i].events < 0) 320 r += strerror(tmp[i].events); 321 else 322 r += sEventFlagsHandler.RenderValue(context, tmp[i].events); 323 324 if (tmp[i].user_data != NULL) { 325 r += ", user_data="; 326 r += context.FormatPointer(tmp[i].user_data); 327 } 328 r += "}"; 329 } 330 331 r += "]"; 332 return r; 333 } 334 335 336 template<> 337 string 338 TypeHandlerImpl<event_wait_info *>::GetParameterValue(Context &context, Parameter *param, 339 const void *address) 340 { 341 void *data = *(void **)address; 342 if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) 343 return read_event_wait_infos(context, param, data); 344 return context.FormatPointer(data); 345 } 346 347 348 template<> 349 string 350 TypeHandlerImpl<event_wait_info *>::GetReturnValue(Context &context, uint64 value) 351 { 352 return context.FormatPointer((void *)value); 353 } 354 355 356 DEFINE_TYPE(fdset_ptr, fd_set *) 357 DEFINE_TYPE(pollfd_ptr, pollfd *) 358 DEFINE_TYPE(object_wait_infos_ptr, object_wait_info *) 359 DEFINE_TYPE(event_wait_infos_ptr, event_wait_info *) 360 361 362 // #pragma mark - patch function 363 364 365 void 366 patch_events() 367 { 368 for (int i = 0; kPollFlagInfos[i].name != NULL; i++) 369 kPollFlags.push_back(kPollFlagInfos[i]); 370 for (int i = 0; kEventFlagInfos[i].name != NULL; i++) 371 kEventFlags.push_back(kEventFlagInfos[i]); 372 373 Syscall *poll = get_syscall("_kern_poll"); 374 poll->ParameterAt(0)->SetInOut(true); 375 376 Syscall *select = get_syscall("_kern_select"); 377 select->ParameterAt(1)->SetInOut(true); 378 select->ParameterAt(2)->SetInOut(true); 379 select->ParameterAt(3)->SetInOut(true); 380 381 Syscall *wait_for_objects = get_syscall("_kern_wait_for_objects"); 382 wait_for_objects->ParameterAt(0)->SetInOut(true); 383 384 Syscall *event_queue_select = get_syscall("_kern_event_queue_select"); 385 event_queue_select->ParameterAt(1)->SetInOut(true); 386 387 Syscall *event_queue_wait = get_syscall("_kern_event_queue_wait"); 388 event_queue_wait->ParameterAt(1)->SetOut(true); 389 390 Syscall *wait_for_child = get_syscall("_kern_wait_for_child"); 391 wait_for_child->ParameterAt(2)->SetOut(true); 392 wait_for_child->ParameterAt(3)->SetOut(true); 393 394 Syscall *wait_for_thread = get_syscall("_kern_wait_for_thread"); 395 wait_for_thread->ParameterAt(1)->SetOut(true); 396 397 Syscall *wait_for_thread_etc = get_syscall("_kern_wait_for_thread_etc"); 398 wait_for_thread_etc->ParameterAt(3)->SetOut(true); 399 } 400