sanitizer_procmaps_bsd.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //===-- sanitizer_procmaps_bsd.cpp ----------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Information about the process mappings
  10. // (FreeBSD and NetBSD-specific parts).
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_platform.h"
  13. #if SANITIZER_FREEBSD || SANITIZER_NETBSD
  14. #include "sanitizer_common.h"
  15. #if SANITIZER_FREEBSD
  16. #include "sanitizer_freebsd.h"
  17. #endif
  18. #include "sanitizer_procmaps.h"
  19. // clang-format off
  20. #include <sys/types.h>
  21. #include <sys/sysctl.h>
  22. // clang-format on
  23. #include <unistd.h>
  24. #if SANITIZER_FREEBSD
  25. #include <sys/user.h>
  26. #endif
  27. #include <limits.h>
  28. // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
  29. #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
  30. #include <osreldate.h>
  31. #if __FreeBSD_version <= 902001 // v9.2
  32. #define kinfo_vmentry xkinfo_vmentry
  33. #endif
  34. #endif
  35. namespace __sanitizer {
  36. #if SANITIZER_FREEBSD
  37. void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
  38. const int Mib[] = {
  39. CTL_KERN,
  40. KERN_PROC,
  41. KERN_PROC_PID,
  42. getpid()
  43. };
  44. struct kinfo_proc InfoProc;
  45. uptr Len = sizeof(InfoProc);
  46. CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0);
  47. cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats);
  48. }
  49. #endif
  50. void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
  51. const int Mib[] = {
  52. #if SANITIZER_FREEBSD
  53. CTL_KERN,
  54. KERN_PROC,
  55. KERN_PROC_VMMAP,
  56. getpid()
  57. #elif SANITIZER_NETBSD
  58. CTL_VM,
  59. VM_PROC,
  60. VM_PROC_MAP,
  61. getpid(),
  62. sizeof(struct kinfo_vmentry)
  63. #else
  64. #error "not supported"
  65. #endif
  66. };
  67. uptr Size = 0;
  68. int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);
  69. CHECK_EQ(Err, 0);
  70. CHECK_GT(Size, 0);
  71. size_t MmapedSize = Size * 4 / 3;
  72. void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
  73. Size = MmapedSize;
  74. Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);
  75. CHECK_EQ(Err, 0);
  76. proc_maps->data = (char *)VmMap;
  77. proc_maps->mmaped_size = MmapedSize;
  78. proc_maps->len = Size;
  79. }
  80. bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
  81. CHECK(!Error()); // can not fail
  82. char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
  83. if (data_.current >= last)
  84. return false;
  85. const struct kinfo_vmentry *VmEntry =
  86. (const struct kinfo_vmentry *)data_.current;
  87. segment->start = (uptr)VmEntry->kve_start;
  88. segment->end = (uptr)VmEntry->kve_end;
  89. segment->offset = (uptr)VmEntry->kve_offset;
  90. segment->protection = 0;
  91. if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
  92. segment->protection |= kProtectionRead;
  93. if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
  94. segment->protection |= kProtectionWrite;
  95. if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
  96. segment->protection |= kProtectionExecute;
  97. if (segment->filename != NULL && segment->filename_size > 0) {
  98. internal_snprintf(segment->filename,
  99. Min(segment->filename_size, (uptr)PATH_MAX), "%s",
  100. VmEntry->kve_path);
  101. }
  102. #if SANITIZER_FREEBSD
  103. data_.current += VmEntry->kve_structsize;
  104. #else
  105. data_.current += sizeof(*VmEntry);
  106. #endif
  107. return true;
  108. }
  109. } // namespace __sanitizer
  110. #endif