|
From: <sv...@va...> - 2015-05-16 16:24:26
|
Author: florian
Date: Sat May 16 17:24:19 2015
New Revision: 15244
Log:
Add VG_(am_stack_limits) and use it in VG_(stack_limits).
With this change the implementation detail call "reservation
segment" is hidden in the address space manager.
Modified:
branches/ASPACEM_TWEAKS/coregrind/m_aspacemgr/aspacemgr-linux.c
branches/ASPACEM_TWEAKS/coregrind/m_stacks.c
branches/ASPACEM_TWEAKS/coregrind/pub_core_aspacemgr.h
Modified: branches/ASPACEM_TWEAKS/coregrind/m_aspacemgr/aspacemgr-linux.c
==============================================================================
--- branches/ASPACEM_TWEAKS/coregrind/m_aspacemgr/aspacemgr-linux.c (original)
+++ branches/ASPACEM_TWEAKS/coregrind/m_aspacemgr/aspacemgr-linux.c Sat May 16 17:24:19 2015
@@ -1307,6 +1307,48 @@
}
}
+
+/* If ADDR is located in a stack segment return True and set return via
+ START and END the address limits of that segment. Otherwise, return
+ False and set the limts to 0. */
+Bool VG_(am_stack_limits)( Addr addr, /*OUT*/Addr *start, /*OUT*/Addr *end )
+{
+ const NSegment *seg = nsegments + find_nsegment_idx(addr);
+
+ switch (seg->kind) {
+ case SkFree:
+ goto bad;
+
+ case SkAnonC:
+ case SkFileC:
+ case SkShmC:
+ case SkAnonV:
+ case SkFileV:
+ if (!seg->hasR || !seg->hasW) goto bad;
+ *start = seg->start;
+ *end = seg->end;
+ return True;
+
+ case SkResvn:
+ /* If ADDR is an unmapped address in an extensible client stack
+ then this is OK. */
+ if (seg->smode != SmUpper) goto bad;
+ *start = seg->start;
+ seg = VG_(am_next_nsegment)(seg, /*forward*/ True);
+ if (!seg || seg->kind != SkAnonC || !seg->hasR || !seg->hasW) goto bad;
+ *end = seg->end;
+ return True;
+
+ default:
+ aspacem_assert(0);
+ }
+
+ bad:
+ *start = *end = 0;
+ return False;
+}
+
+
/*-----------------------------------------------------------------*/
/*--- ---*/
/*--- Modifying the segment array, and constructing segments. ---*/
Modified: branches/ASPACEM_TWEAKS/coregrind/m_stacks.c
==============================================================================
--- branches/ASPACEM_TWEAKS/coregrind/m_stacks.c (original)
+++ branches/ASPACEM_TWEAKS/coregrind/m_stacks.c Sat May 16 17:24:19 2015
@@ -270,73 +270,43 @@
void VG_(stack_limits)(Addr SP, Addr *start, Addr *end )
{
Stack* stack = find_stack_by_addr(SP);
- NSegment const *stackseg = VG_(am_find_nsegment) (SP);
if (LIKELY(stack)) {
*start = stack->start;
*end = stack->end;
}
- /* SP is assumed to be in a RW segment or in the SkResvn segment of an
- extensible stack (normally, only the main thread has an extensible
- stack segment).
+ /* SP is assumed to be in a stack segment.
If no such segment is found, assume we have no valid
stack for SP, and set *start and *end to 0.
Otherwise, possibly reduce the stack limits using the boundaries of
- the RW segment/SkResvn segments containing SP. */
- if (UNLIKELY(stackseg == NULL)) {
+ the stack segment containing SP. */
+ Addr stackseg_start, stackseg_end;
+ if (UNLIKELY(! VG_(am_stack_limits)(SP, &stackseg_start, &stackseg_end))) {
VG_(debugLog)(2, "stacks",
- "no addressable segment for SP %p\n",
- (void*)SP);
+ "SP %p is not located in a stack segment or stack segment "
+ "has wrong permissions\n", (void*)SP);
*start = 0;
*end = 0;
return;
}
- if (UNLIKELY((!stackseg->hasR || !stackseg->hasW)
- && (stackseg->kind != SkResvn || stackseg->smode != SmUpper))) {
- VG_(debugLog)(2, "stacks",
- "segment for SP %p is not RW or not a SmUpper Resvn\n",
- (void*)SP);
- *start = 0;
- *end = 0;
- return;
- }
-
- /* SP is in a RW segment, or in the SkResvn of an extensible stack.
- We can use the seg start as the stack start limit. */
- if (UNLIKELY(*start < stackseg->start)) {
+ /* SP is located in a stack segment */
+ if (UNLIKELY(*start < stackseg_start)) {
VG_(debugLog)(2, "stacks",
"segment for SP %p changed stack start limit"
" from %p to %p\n",
- (void*)SP, (void*)*start, (void*)stackseg->start);
- *start = stackseg->start;
- }
-
- /* Now, determine the stack end limit. If the stackseg is SkResvn,
- we need to get the neighbour segment (towards higher addresses).
- This segment must be anonymous and RW. */
- if (UNLIKELY(stackseg->kind == SkResvn)) {
- stackseg = VG_(am_next_nsegment)(stackseg, /*forward*/ True);
- if (!stackseg || !stackseg->hasR || !stackseg->hasW
- || stackseg->kind != SkAnonC) {
- VG_(debugLog)(2, "stacks",
- "Next forward segment for SP %p Resvn segment"
- " is not RW or not AnonC\n",
- (void*)SP);
- *start = 0;
- *end = 0;
- return;
- }
+ (void*)SP, (void*)*start, (void*)stackseg_start);
+ *start = stackseg_start;
}
/* Limit the stack end limit, using the found segment. */
- if (UNLIKELY(*end > stackseg->end)) {
+ if (UNLIKELY(*end > stackseg_end)) {
VG_(debugLog)(2, "stacks",
"segment for SP %p changed stack end limit"
" from %p to %p\n",
- (void*)SP, (void*)*end, (void*)stackseg->end);
- *end = stackseg->end;
+ (void*)SP, (void*)*end, (void*)stackseg_end);
+ *end = stackseg_end;
}
/* If reducing start and/or end to the SP segment gives an
Modified: branches/ASPACEM_TWEAKS/coregrind/pub_core_aspacemgr.h
==============================================================================
--- branches/ASPACEM_TWEAKS/coregrind/pub_core_aspacemgr.h (original)
+++ branches/ASPACEM_TWEAKS/coregrind/pub_core_aspacemgr.h Sat May 16 17:24:19 2015
@@ -92,6 +92,11 @@
extensible client stack segment. */
extern Bool VG_(am_addr_is_in_extensible_client_stack)( Addr addr, HChar kind );
+/* If ADDR is located in a segment that looks like a stack segment, return
+ the start and end addresses of that segment. */
+extern Bool VG_(am_stack_limits)( Addr addr, /*OUT*/Addr *start,
+ /*OUT*/Addr *end );
+
/* Trivial fn: return the total amount of space in anonymous mappings,
both for V and the client. Is used for printing stats in
out-of-memory messages. */
|