this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement `PROC_PIDREGIONPATH`

It's basically a lighter version of `PROC_PIDREGIONPATHINFO` with less information: region address, size, and owner path

+136 -31
+136 -31
src/kernel/emulation/linux/misc/proc_info.c
··· 80 80 } 81 81 } 82 82 83 - static bool parse_smaps_firstline(const char* line, struct proc_regioninfo* ri, struct vnode_info_path* vip); 83 + static bool parse_smaps_firstline( 84 + const char* line, 85 + uint64_t* pri_address, 86 + uint64_t* pri_size, 87 + uint32_t* pri_protection, 88 + uint32_t* pri_share_mode, 89 + uint64_t* pri_offset, 90 + uint32_t* vst_dev, 91 + uint64_t* vst_ino, 92 + char* vip_path 93 + ); 84 94 static long _proc_pidinfo_regionpathinfo(int32_t pid, uint64_t arg, void* buffer, int32_t bufsize); 85 95 static long _proc_pidinfo_shortbsdinfo(int32_t pid, void* buffer, int32_t bufsize); 86 96 static long _proc_pidonfo_uniqinfo(int32_t pid, void* buffer, int32_t bufsize); 87 97 static long _proc_pidinfo_tbsdinfo(int32_t pid, void* buffer, int32_t bufsize); 88 98 static long _proc_pidinfo_pidthreadinfo(int32_t pid, uint64_t thread_handle, void* buffer, int32_t bufsize); 89 99 static long _proc_pidinfo_pathinfo(int32_t pid, void* buffer, int32_t bufsize); 100 + static long _proc_pidinfo_regionpath(int32_t pid, uint64_t arg, void* buffer, int32_t buffer_size); 90 101 91 102 long _proc_pidinfo(int32_t pid, uint32_t flavor, uint64_t arg, void* buffer, int32_t bufsize) 92 103 { ··· 119 130 case PROC_PIDPATHINFO: 120 131 { 121 132 return _proc_pidinfo_pathinfo(pid, buffer, bufsize); 133 + } 134 + case PROC_PIDREGIONPATH: 135 + { 136 + return _proc_pidinfo_regionpath(pid, arg, buffer, bufsize); 122 137 } 123 138 default: 124 139 { ··· 338 353 return -EINVAL; 339 354 } 340 355 356 + static long _proc_pidinfo_regionpath_setup(int32_t pid, struct rdline_buffer* buf) { 357 + char proc_path[50]; 358 + int fd; 359 + 360 + __simple_sprintf(proc_path, "/proc/%d/smaps", pid); 361 + fd = sys_open_nocancel(proc_path, BSD_O_RDONLY, 0); 362 + if (fd < 0) 363 + return fd; 364 + 365 + _readline_init(buf); 366 + return fd; 367 + }; 368 + 341 369 static long _proc_pidinfo_regionpathinfo(int32_t pid, uint64_t arg, void* buffer, int32_t bufsize) 342 370 { 343 - union { 344 - char proc_path[50]; 345 - struct rdline_buffer buf; 346 - } vars; // to reduce stack usage 371 + struct rdline_buffer buf; 347 372 int fd; 348 373 const char* line; 349 374 struct proc_regionwithpathinfo my_rpi; ··· 354 379 if (bufsize < sizeof(my_rpi)) 355 380 return -ENOSPC; 356 381 357 - __simple_sprintf(vars.proc_path, "/proc/%d/smaps", pid); 358 - fd = sys_open_nocancel(vars.proc_path, BSD_O_RDONLY, 0); 382 + fd = _proc_pidinfo_regionpath_setup(pid, &buf); 359 383 if (fd < 0) 360 384 return fd; 361 385 362 - _readline_init(&vars.buf); 363 - memset(&my_rpi, 0, sizeof(my_rpi)); 364 - 365 - while ((line = _readline(fd, &vars.buf)) != NULL) 386 + while ((line = _readline(fd, &buf)) != NULL) 366 387 { 367 388 if (!foundRegion) 368 389 { 369 390 // Searching for matching memory region. 370 391 // This call returns true if we see the start of another mapping. 371 - if (parse_smaps_firstline(line, &my_rpi.prp_prinfo, &my_rpi.prp_vip)) 392 + if (parse_smaps_firstline( 393 + line, 394 + &my_rpi.prp_prinfo.pri_address, 395 + &my_rpi.prp_prinfo.pri_size, 396 + &my_rpi.prp_prinfo.pri_protection, 397 + &my_rpi.prp_prinfo.pri_share_mode, 398 + &my_rpi.prp_prinfo.pri_offset, 399 + &my_rpi.prp_vip.vip_vi.vi_stat.vst_dev, 400 + &my_rpi.prp_vip.vip_vi.vi_stat.vst_ino, 401 + my_rpi.prp_vip.vip_path 402 + )) 372 403 { 373 404 if (arg >= my_rpi.prp_prinfo.pri_address && arg < (my_rpi.prp_prinfo.pri_address + my_rpi.prp_prinfo.pri_size)) 374 405 { ··· 392 423 return foundRegion ? 1 : -ESRCH; 393 424 } 394 425 426 + static long _proc_pidinfo_regionpath(int32_t pid, uint64_t arg, void* buffer, int32_t buffer_size) { 427 + // `_proc_pidinfo_regionpathinfo` is a glutton for stack space, due to the size of `struct proc_regioninfo` 428 + // 429 + // so rather than calling it and extracting the necessary information, it's better to have most of the common code 430 + // moved out and duplicate some minimal amounts of code for this function 431 + 432 + struct proc_regionpath my_rp; 433 + int fd; 434 + struct rdline_buffer readline_buffer; 435 + const char* line; 436 + bool found = false; 437 + 438 + if (!buffer) 439 + return -EFAULT; 440 + if (buffer_size < sizeof(my_rp)) 441 + return -ENOSPC; 442 + 443 + fd = _proc_pidinfo_regionpath_setup(pid, &readline_buffer); 444 + if (fd < 0) 445 + return fd; 446 + 447 + while ((line = _readline(fd, &readline_buffer)) != NULL) { 448 + if (parse_smaps_firstline( 449 + line, 450 + &my_rp.prpo_addr, 451 + &my_rp.prpo_regionlength, 452 + NULL, 453 + NULL, 454 + NULL, 455 + NULL, 456 + NULL, 457 + my_rp.prpo_path 458 + )) { 459 + if (arg >= my_rp.prpo_addr && arg < (my_rp.prpo_addr + my_rp.prpo_regionlength)) { 460 + found = true; 461 + break; 462 + } 463 + } 464 + } 465 + 466 + close_internal(fd); 467 + 468 + memcpy(buffer, &my_rp, sizeof(my_rp)); 469 + return found ? 0 : -EINVAL; 470 + }; 471 + 395 472 // Parses line such as: 396 473 // 5568e1914000-5568e1915000 r--p 00024000 08:01 4861625 /usr/bin/less 397 - static bool parse_smaps_firstline(const char* line, struct proc_regioninfo* ri, struct vnode_info_path* vip) 474 + static bool parse_smaps_firstline( 475 + const char* line, 476 + uint64_t* pri_address, 477 + uint64_t* pri_size, 478 + uint32_t* pri_protection, 479 + uint32_t* pri_share_mode, 480 + uint64_t* pri_offset, 481 + uint32_t* vst_dev, 482 + uint64_t* vst_ino, 483 + char* vip_path 484 + ) 398 485 { 399 486 const char* p; 400 487 const char* minus = NULL; 488 + uint64_t backup_variable; 489 + 490 + if (!pri_address) 491 + pri_address = &backup_variable; 401 492 402 493 // Read address range 403 494 p = line; ··· 405 496 { 406 497 if (*p == '-') 407 498 { 408 - ri->pri_address = __simple_atoi16(line, NULL); 499 + *pri_address = __simple_atoi16(line, NULL); 409 500 minus = p; 410 501 } 411 502 p++; ··· 413 504 if (!minus) 414 505 return false; // this is a different line 415 506 416 - ri->pri_size = __simple_atoi16(minus+1, NULL) - ri->pri_address; 507 + if (pri_size) 508 + *pri_size = __simple_atoi16(minus+1, NULL) - *pri_address; 417 509 p++; 418 510 419 511 // Now read protection 420 - ri->pri_protection = 0; 421 - if (*p++ == 'r') 422 - ri->pri_protection |= VM_PROT_READ; 423 - if (*p++ == 'w') 424 - ri->pri_protection |= VM_PROT_WRITE; 425 - if (*p++ == 'x') 426 - ri->pri_protection |= VM_PROT_EXECUTE; 512 + if (pri_protection) { 513 + *pri_protection = 0; 514 + if (*p++ == 'r') 515 + *pri_protection |= VM_PROT_READ; 516 + if (*p++ == 'w') 517 + *pri_protection |= VM_PROT_WRITE; 518 + if (*p++ == 'x') 519 + *pri_protection |= VM_PROT_EXECUTE; 520 + } else { 521 + p += 3; 522 + } 427 523 428 - if (*p++ == 'p') // COW/private 429 - ri->pri_share_mode = SM_PRIVATE; 430 - else 431 - ri->pri_share_mode = SM_SHARED; 524 + if (pri_share_mode) { 525 + if (*p++ == 'p') // COW/private 526 + *pri_share_mode = SM_PRIVATE; 527 + else 528 + *pri_share_mode = SM_SHARED; 529 + } else { 530 + p++; 531 + } 432 532 p++; // space 433 533 434 534 // Read file offset 435 - ri->pri_offset = __simple_atoi16(p, &p); 535 + if (!pri_offset) 536 + pri_offset = &backup_variable; 537 + *pri_offset = __simple_atoi16(p, &p); 436 538 p++; 437 539 438 540 // Read device major:minor ··· 441 543 p++; 442 544 min = (int) __simple_atoi16(p, &p); 443 545 p++; 444 - vip->vip_vi.vi_stat.vst_dev = (maj << 8) | min; 546 + if (vst_dev) 547 + *vst_dev = (maj << 8) | min; 445 548 446 549 // Read inode 447 - vip->vip_vi.vi_stat.vst_ino = __simple_atoi(p, &p); 550 + if (!vst_ino) 551 + vst_ino = &backup_variable; 552 + *vst_ino = __simple_atoi(p, &p); 448 553 449 554 // Read file name (may be empty) 450 555 while (*p == ' ') 451 556 p++; 452 - if (*p) // Is file name present? 453 - strcpy(vip->vip_path, p); 557 + if (*p && vip_path) // Is file name present? (and the caller wants it) 558 + strcpy(vip_path, p); 454 559 455 560 return true; 456 561 }