mirror of
https://github.com/DynamoRIO/dynamorio.git
synced 2026-10-12 02:02:04 +00:00
i#2037: update memcache on re-takeover and query miss (#2870)
Adds a complete maps file walk to update the memcache on re-taking-over the process for dr_api_start. The memcache is cleared beforehand to avoid both false positives and negatives in later queries. This helps to solve issues with a gap between dr_app_setup() and dr_app_start(). Does not update the executable areas or module list: they are more difficult to re-walk, and existing lazy updates to those will suffice for now, with a low risk of false positives. Adds updating of the memcache on a query miss. Previously we would just continue to miss and walk the maps file every time. Tested manually by disabling the i#2114 change so that a signal does a query, adding signals to the burst_threads test, and calling dr_app_setup() before creating the test's threads, causing queries to miss when delivering signals. It is difficult to create a regression test for this as the consequences are performance degradations rather than correctness, and these degradations only really show up at scale with hundreds of threads whose missing stacks are queried at once with no caching. Fixes #2037
This commit is contained in:
+24
-14
@@ -1,5 +1,5 @@
|
||||
/* *******************************************************************************
|
||||
* Copyright (c) 2010-2017 Google, Inc. All rights reserved.
|
||||
* Copyright (c) 2010-2018 Google, Inc. All rights reserved.
|
||||
* Copyright (c) 2011 Massachusetts Institute of Technology All rights reserved.
|
||||
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
|
||||
* *******************************************************************************/
|
||||
@@ -446,25 +446,18 @@ memcache_query_memory(const byte *pc, OUT dr_mem_info_t *out_info)
|
||||
* are holes in all_memory_areas
|
||||
*/
|
||||
from_os_prot != MEMPROT_NONE) {
|
||||
/* FIXME i#2037: today the start/stop API does not re-scan on start,
|
||||
* so our cache is wrong. Worse than a false negative here, which we
|
||||
* can handle as lazy lookup, is a false positive: we need to clear the
|
||||
* cache at start. For now we just quiet the complaints here.
|
||||
*/
|
||||
DODEBUG({
|
||||
if (!dr_api_entry) {
|
||||
SYSLOG_INTERNAL_ERROR
|
||||
("all_memory_areas is missing region " PFX"-"PFX"!",
|
||||
from_os_base_pc, from_os_base_pc + from_os_size);
|
||||
}
|
||||
});
|
||||
SYSLOG_INTERNAL_WARNING_ONCE
|
||||
("all_memory_areas is missing regions including " PFX"-"PFX,
|
||||
from_os_base_pc, from_os_base_pc + from_os_size);
|
||||
DOLOG(4, LOG_VMAREAS, memcache_print(THREAD_GET, ""););
|
||||
ASSERT(dr_api_entry);
|
||||
/* be paranoid */
|
||||
out_info->base_pc = from_os_base_pc;
|
||||
out_info->size = from_os_size;
|
||||
out_info->prot = from_os_prot;
|
||||
out_info->type = DR_MEMTYPE_DATA; /* hopefully we won't miss an image */
|
||||
/* Update our list to avoid coming back here again (i#2037). */
|
||||
memcache_update_locked(from_os_base_pc, from_os_base_pc+from_os_size,
|
||||
from_os_prot, -1, false/*!exists*/);
|
||||
}
|
||||
#else
|
||||
/* We now have nested probes, but currently probing sometimes calls
|
||||
@@ -585,3 +578,20 @@ memcache_handle_app_brk(byte *lowest_brk/*if known*/, byte *old_brk, byte *new_b
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
memcache_update_all_from_os(void)
|
||||
{
|
||||
memquery_iter_t iter;
|
||||
LOG(GLOBAL, LOG_SYSCALLS, 1, "updating memcache from maps file\n");
|
||||
memquery_iterator_start(&iter, NULL, true/*may alloc*/);
|
||||
memcache_lock();
|
||||
/* We clear the entire cache to avoid false positive queries. */
|
||||
vmvector_reset_vector(GLOBAL_DCONTEXT, all_memory_areas);
|
||||
while (memquery_iterator_next(&iter)) {
|
||||
/* We do a heavyweight overlap check with everything. */
|
||||
memcache_update_locked(iter.vm_start, iter.vm_end, iter.prot,
|
||||
-1, false/*!exists*/);
|
||||
}
|
||||
memcache_unlock();
|
||||
memquery_iterator_stop(&iter);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* **********************************************************
|
||||
* Copyright (c) 2013-2015 Google, Inc. All rights reserved.
|
||||
* Copyright (c) 2013-2018 Google, Inc. All rights reserved.
|
||||
* **********************************************************/
|
||||
|
||||
/*
|
||||
@@ -78,4 +78,7 @@ memcache_handle_mremap(dcontext_t *dcontext, byte *base, size_t size,
|
||||
void
|
||||
memcache_handle_app_brk(byte *lowest_brk/*if known*/, byte *old_brk, byte *new_brk);
|
||||
|
||||
void
|
||||
memcache_update_all_from_os(void);
|
||||
|
||||
#endif /* _MEMCACHE_H_ */
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/* *******************************************************************************
|
||||
* Copyright (c) 2010-2017 Google, Inc. All rights reserved.
|
||||
* Copyright (c) 2010-2018 Google, Inc. All rights reserved.
|
||||
* Copyright (c) 2011 Massachusetts Institute of Technology All rights reserved.
|
||||
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
|
||||
* *******************************************************************************/
|
||||
@@ -2597,6 +2597,13 @@ os_process_under_dynamorio_complete(dcontext_t *dcontext)
|
||||
{
|
||||
/* i#2161: only now do we un-ignore alarm signals. */
|
||||
signal_reinstate_alarm_handlers(dcontext);
|
||||
IF_NO_MEMQUERY({
|
||||
/* Update the memory cache (i#2037) now that we've taken over all the
|
||||
* threads, if there may have been a gap between setup and start.
|
||||
*/
|
||||
if (dr_api_entry)
|
||||
memcache_update_all_from_os();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+6
-6
@@ -2116,6 +2116,12 @@ vmvector_reset_vector(dcontext_t *dcontext, vm_area_vector_t *v)
|
||||
});
|
||||
/* with thread shared cache it is in fact possible to have no thread local vmareas */
|
||||
if (v->buf != NULL) {
|
||||
if (v->free_payload_func != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < v->length; i++) {
|
||||
v->free_payload_func(v->buf[i].custom.client);
|
||||
}
|
||||
}
|
||||
/* FIXME: walk through and make sure frags lists are all freed */
|
||||
global_heap_free(v->buf, v->size*sizeof(struct vm_area_t) HEAPACCT(ACCT_VMAREAS));
|
||||
v->size = 0;
|
||||
@@ -2136,12 +2142,6 @@ vmvector_free_vector(dcontext_t *dcontext, vm_area_vector_t *v)
|
||||
void
|
||||
vmvector_delete_vector(dcontext_t *dcontext, vm_area_vector_t *v)
|
||||
{
|
||||
if (v->free_payload_func != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < v->length; i++) {
|
||||
v->free_payload_func(v->buf[i].custom.client);
|
||||
}
|
||||
}
|
||||
vmvector_free_vector(dcontext, v);
|
||||
HEAP_TYPE_FREE(dcontext, v, vm_area_vector_t, ACCT_VMAREAS, PROTECTED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user