blob: 09c6016bd31ccefd560394764fae950d5fa7df0d [file] [log] [blame] [edit]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <mach/mach.h>
#include <mach/mach_vm.h>
typedef struct {
void* isa;
int flags;
// There are other fields, but we just need the flags and isa.
} BlockRefCountExtractor;
uint64_t getBlockRetainCount(BlockRefCountExtractor* block) {
// The ref count is stored in the lower bits of the flags field, but skips the
// 0x1 bit.
return (block->flags & 0xFFFF) >> 1;
}
typedef struct {
uint64_t header;
} ObjectRefCountExtractor;
static const uint64_t k128OrMore = 128;
// Returns the ref count of the object, up to 127. For counts above this, always
// returns k128OrMore.
uint64_t getObjectRetainCount(ObjectRefCountExtractor* object) {
uint64_t count = object->header >> 56;
return count < 0x80 ? count : k128OrMore;
}
int isReadableMemory(void* ptr) {
vm_map_t task = mach_task_self();
mach_vm_address_t address = (mach_vm_address_t)ptr;
mach_vm_size_t size = 0;
vm_region_basic_info_data_64_t info;
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
mach_port_t object_name;
kern_return_t status =
mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64,
(vm_region_info_t)&info, &count, &object_name);
if (status != KERN_SUCCESS) return 0;
return ((mach_vm_address_t)ptr) >= address &&
(info.protection & VM_PROT_READ);
}