Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 79 additions & 17 deletions compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
# endif
# include <stdio.h>

// Start searching for available memory region past PAGEZERO, which is
// 4KB on 32-bit and 4GB on 64-bit.
# define GAP_SEARCH_START_ADDRESS \
((SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000)

# include "sanitizer_common.h"
# include "sanitizer_file.h"
# include "sanitizer_flags.h"
Expand Down Expand Up @@ -58,6 +63,7 @@ extern char ***_NSGetArgv(void);
# include <dlfcn.h> // for dladdr()
# include <errno.h>
# include <fcntl.h>
# include <inttypes.h>
# include <libkern/OSAtomic.h>
# include <mach-o/dyld.h>
# include <mach/mach.h>
Expand Down Expand Up @@ -1106,6 +1112,67 @@ static void StripEnv() {
}
#endif // SANITIZER_GO

// Prints out a consolidated memory map: contiguous regions
// are merged together.
static void PrintVmmap() {
const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
kern_return_t kr = KERN_SUCCESS;

Report("Memory map:\n");
mach_vm_address_t last = 0;
mach_vm_address_t lastsz = 0;

while (1) {
mach_vm_size_t vmsize = 0;
natural_t depth = 0;
vm_region_submap_short_info_data_64_t vminfo;
mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
(vm_region_info_t)&vminfo, &count);

if (kr == KERN_DENIED) {
Report(
"ERROR: mach_vm_region_recurse got KERN_DENIED when printing memory "
"map.\n");
Report(
"HINT: Check whether mach_vm_region_recurse is allowed by "
"sandbox.\n");
}

if (kr == KERN_SUCCESS && address < max_vm_address) {
if (last + lastsz == address) {
// This region is contiguous with the last; merge together.
lastsz += vmsize;
} else {
if (lastsz)
Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", last,
last + lastsz, lastsz);

last = address;
lastsz = vmsize;
}
address += vmsize;
} else {
// We've reached the end of the memory map. Print the last remaining
// region, if there is one.
if (lastsz)
Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", last,
last + lastsz, lastsz);

break;
}
}
}

static void ReportShadowAllocFail(uptr shadow_size_bytes, uptr alignment) {
Report(
"FATAL: Failed to allocate shadow memory. Tried to allocate %p bytes "
"(alignment=%p).\n",
shadow_size_bytes, alignment);
PrintVmmap();
}

char **GetArgv() {
return *_NSGetArgv();
}
Expand Down Expand Up @@ -1213,10 +1280,11 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
if (new_max_vm < max_occupied_addr) {
Report("Unable to find a memory range for dynamic shadow.\n");
Report(
"space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
"new_max_vm = %p\n",
(void *)space_size, (void *)largest_gap_found,
(void *)max_occupied_addr, (void *)new_max_vm);
"\tspace_size = %p\n\tlargest_gap_found = %p\n\tmax_occupied_addr "
"= %p\n\tnew_max_vm = %p\n",
(void*)space_size, (void*)largest_gap_found, (void*)max_occupied_addr,
(void*)new_max_vm);
ReportShadowAllocFail(shadow_size_bytes, alignment);
CHECK(0 && "cannot place shadow");
}
RestrictMemoryToMaxAddress(new_max_vm);
Expand All @@ -1227,6 +1295,7 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
nullptr, nullptr);
if (shadow_start == 0) {
Report("Unable to find a memory range after restricting VM.\n");
ReportShadowAllocFail(shadow_size_bytes, alignment);
CHECK(0 && "cannot place shadow after restricting vm");
}
}
Expand All @@ -1242,26 +1311,19 @@ uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
}

uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
uptr *largest_gap_found,
uptr *max_occupied_addr) {
typedef vm_region_submap_short_info_data_64_t RegionInfo;
enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
// Start searching for available memory region past PAGEZERO, which is
// 4KB on 32-bit and 4GB on 64-bit.
mach_vm_address_t start_address =
(SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;

uptr* largest_gap_found,
uptr* max_occupied_addr) {
const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
mach_vm_address_t address = start_address;
mach_vm_address_t free_begin = start_address;
mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
mach_vm_address_t free_begin = GAP_SEARCH_START_ADDRESS;
kern_return_t kr = KERN_SUCCESS;
if (largest_gap_found) *largest_gap_found = 0;
if (max_occupied_addr) *max_occupied_addr = 0;
while (kr == KERN_SUCCESS) {
mach_vm_size_t vmsize = 0;
natural_t depth = 0;
RegionInfo vminfo;
mach_msg_type_number_t count = kRegionInfoSize;
vm_region_submap_short_info_data_64_t vminfo;
mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
(vm_region_info_t)&vminfo, &count);

Expand Down