Implement getMemRanges() on the Mac

develop
Timothy Collett 2012-06-14 13:43:20 -04:00
parent 9c35e9fa59
commit 14a3e5cd9e
1 changed files with 62 additions and 23 deletions

@ -124,33 +124,72 @@ string Process::doReadClassName (void * vptr)
return raw.substr(start,end-start); return raw.substr(start,end-start);
} }
//FIXME: cross-reference with ELF segment entries? #include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/vm_region.h>
#include <mach/vm_statistics.h>
#include <dlfcn.h>
void Process::getMemRanges( vector<t_memrange> & ranges ) void Process::getMemRanges( vector<t_memrange> & ranges )
{ {
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
FILE *mapFile = ::fopen("/proc/self/maps", "r"); kern_return_t kr;
size_t start, end, offset, device1, device2, node; task_t the_task;
the_task = mach_task_self();
vm_size_t vmsize;
vm_address_t address;
vm_region_basic_info_data_t info;
mach_msg_type_number_t info_count;
vm_region_flavor_t flavor;
memory_object_name_t object;
kr = KERN_SUCCESS;
address = 0;
do {
flavor = VM_REGION_BASIC_INFO;
info_count = VM_REGION_BASIC_INFO_COUNT;
kr = vm_region(the_task, &address, &vmsize, flavor,
(vm_region_info_t)&info, &info_count, &object);
if (kr == KERN_SUCCESS) {
if (info.reserved==1) {
address += vmsize;
continue;
}
Dl_info dlinfo;
int dlcheck;
dlcheck = dladdr((const void*)address, &dlinfo);
if (dlcheck==0) {
dlinfo.dli_fname = "(none)";
}
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp; t_memrange temp;
temp.name[0] = 0; strncpy( temp.name, dlinfo.dli_fname, 1023 );
sscanf(buffer, "%zx-%zx %s %zx %2zx:%2zx %zu %[^\n]", temp.name[1023] = 0;
&start, temp.start = (void *) address;
&end, temp.end = (void *) (address+vmsize);
(char*)&permissions, temp.read = (info.protection & VM_PROT_READ);
&offset, &device1, &device2, &node, temp.write = (info.protection & VM_PROT_WRITE);
(char*)temp.name); temp.execute = (info.protection & VM_PROT_EXECUTE);
temp.start = (void *) start; temp.shared = info.shared;
temp.end = (void *) end;
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
temp.shared = permissions[3] == 's';
temp.valid = true; temp.valid = true;
ranges.push_back(temp); ranges.push_back(temp);
address += vmsize;
} else if (kr != KERN_INVALID_ADDRESS) {
if (the_task != MACH_PORT_NULL) {
mach_port_deallocate(mach_task_self(), the_task);
}
return;
}
} while (kr != KERN_INVALID_ADDRESS);
if (the_task != MACH_PORT_NULL) {
mach_port_deallocate(mach_task_self(), the_task);
} }
} }