Skip to content

Commit

Permalink
i#58 MacOS: determine the file backing a memory region
Browse files Browse the repository at this point in the history
My implementation uses SYS_proc_info with PROC_INFO_PID_INFO and
PROC_PIDREGIONPATHINFO to get the file backing information.

I tweaked the library bounds code to allow allocating memory by the
memory iterator, as Mac's uses heap instead of a locked static struct.
The heap is used to hold the large buffer for the file backing query.

SVN-Revision: 2465
  • Loading branch information
derekbruening committed Jan 9, 2014
1 parent 1fdd760 commit 5af2c1a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 7 deletions.
5 changes: 4 additions & 1 deletion core/unix/memquery.h
@@ -1,5 +1,5 @@
/* *******************************************************************************
* Copyright (c) 2013 Google, Inc. All rights reserved.
* Copyright (c) 2013-2014 Google, Inc. All rights reserved.
* *******************************************************************************/

/*
Expand Down Expand Up @@ -77,6 +77,9 @@ memquery_exit(void);
/* The passed-in "start" parameter is a performance hint to start
* iteration at the region containing that address. However, the
* iterator may start before that point.
*
* Pass true for may_alloc, unless the caller is in a fragile situation (e.g.,
* a signal handler) where we shouldn't allocate heap.
*/
bool
memquery_iterator_start(memquery_iter_t *iter, app_pc start, bool may_alloc);
Expand Down
4 changes: 2 additions & 2 deletions core/unix/memquery_linux.c
@@ -1,5 +1,5 @@
/* *******************************************************************************
* Copyright (c) 2010-2013 Google, Inc. All rights reserved.
* Copyright (c) 2010-2014 Google, Inc. All rights reserved.
* Copyright (c) 2011 Massachusetts Institute of Technology All rights reserved.
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
* *******************************************************************************/
Expand Down Expand Up @@ -314,7 +314,7 @@ memquery_library_bounds(const char *name, app_pc *start/*IN/OUT*/, app_pc *end/*
app_pc mod_start = NULL;
ASSERT(name != NULL || start != NULL);

memquery_iterator_start(&iter, NULL, false/*won't alloc*/);
memquery_iterator_start(&iter, NULL, true/*ok to alloc*/);
libname[0] = '\0';
while (memquery_iterator_next(&iter)) {
LOG(GLOBAL, LOG_VMAREAS, 5,"start="PFX" end="PFX" prot=%x comment=%s\n",
Expand Down
61 changes: 58 additions & 3 deletions core/unix/memquery_macos.c
Expand Up @@ -45,15 +45,33 @@
#include <mach/mach.h>
#include <mach/mach_vm.h>

/* For querying which file backs an mmap */
#include <libproc.h>
#include <sys/proc_info.h>
#include <sys/syscall.h>

#ifndef MACOS
# error Mac-only
#endif

/* Code passed to SYS_proc_info */
#define PROC_INFO_PID_INFO 2

/* We need a large (1272 byte) structure to obtain file backing info.
* For regular queries we allocate this on the heap, but for fragile no-alloc
* queries we use a static struct.
*/
static struct proc_regionwithpathinfo backing_info;
static mutex_t memquery_backing_lock = INIT_LOCK_FREE(memquery_backing_lock);

/* Internal data */
typedef struct _internal_iter_t {
struct vm_region_submap_info_64 info;
vm_address_t address;
uint32_t depth;
/* This points at either the heap or the global backing_info */
struct proc_regionwithpathinfo *backing;
dcontext_t *dcontext; /* GLOBAL_DCONTEXT for global heap; NULL for global struct */
} internal_iter_t;

void
Expand All @@ -66,6 +84,24 @@ memquery_init(void)
void
memquery_exit(void)
{
DELETE_LOCK(memquery_backing_lock);
}

static bool
memquery_file_backing(struct proc_regionwithpathinfo *info, app_pc addr)
{
int res;
#ifdef X64
res = dynamorio_syscall(SYS_proc_info, 6, PROC_INFO_PID_INFO, get_process_id(),
PROC_PIDREGIONPATHINFO, (uint64_t)addr, info, sizeof(*info));
#else
res = dynamorio_syscall(SYS_proc_info, 7, PROC_INFO_PID_INFO, get_process_id(),
PROC_PIDREGIONPATHINFO,
/* represent 64-bit arg as 2 32-bit args */
addr, NULL,
info, sizeof(*info));
#endif
return (res >= 0);
}

int
Expand All @@ -83,13 +119,29 @@ memquery_iterator_start(memquery_iter_t *iter, app_pc start, bool may_alloc)
memset(ii, 0, sizeof(*ii));
ii->address = (vm_address_t) start;
iter->may_alloc = may_alloc;
if (may_alloc) {
ii->dcontext = get_thread_private_dcontext();
if (ii->dcontext == NULL)
ii->dcontext = GLOBAL_DCONTEXT;
ii->backing = HEAP_TYPE_ALLOC(ii->dcontext, struct proc_regionwithpathinfo,
ACCT_MEM_MGT, PROTECTED);
} else {
mutex_lock(&memquery_backing_lock);
ii->backing = &backing_info;
ii->dcontext = NULL;
}
return true;
}

void
memquery_iterator_stop(memquery_iter_t *iter)
{
/* nothing */
internal_iter_t *ii = (internal_iter_t *) &iter->internal;
if (ii->dcontext != NULL) {
HEAP_TYPE_FREE(ii->dcontext, ii->backing, struct proc_regionwithpathinfo,
ACCT_MEM_MGT, PROTECTED);
} else
mutex_unlock(&memquery_backing_lock);
}

/* Translate mach flags to memprot flags. They happen to equal the mmap
Expand Down Expand Up @@ -144,8 +196,11 @@ memquery_iterator_next(memquery_iter_t *iter)
iter->prot = vmprot_to_memprot(ii->info.protection);
iter->offset = 0; /* XXX: not filling in */
iter->inode = 0; /* XXX: not filling in */
/* FIXME i#58: fill this in via SYS_proc_info */
iter->comment = "";
if (memquery_file_backing(ii->backing, iter->vm_start)) {
NULL_TERMINATE_BUFFER(ii->backing->prp_vip.vip_path);
iter->comment = ii->backing->prp_vip.vip_path;
} else
iter->comment = "";

LOG(GLOBAL, LOG_ALL, 5, "%s: returning "PFX"-"PFX" prot=0x%x %s\n",
__FUNCTION__, iter->vm_start, iter->vm_end, iter->prot, iter->comment);
Expand Down
4 changes: 3 additions & 1 deletion core/utils.h
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2010-2013 Google, Inc. All rights reserved.
* Copyright (c) 2010-2014 Google, Inc. All rights reserved.
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
* **********************************************************/

Expand Down Expand Up @@ -574,6 +574,8 @@ enum {
*/
#ifdef LINUX
LOCK_RANK(memory_info_buf_lock),
#elif defined(MACOS)
LOCK_RANK(memquery_backing_lock),
#endif
#ifdef WINDOWS
LOCK_RANK(dump_core_lock),
Expand Down

0 comments on commit 5af2c1a

Please sign in to comment.