Exemplo n.º 1
0
/*
 * Find the bounds of the stack (if any) which includes the
 * specified stack pointer.
 */
void VG_(stack_limits)(Addr SP, Addr *start, Addr *end )
{
   Stack* stack = find_stack_by_addr(SP);

   if (stack) {
      *start = stack->start;
      *end = stack->end;
   }
}
Exemplo n.º 2
0
/*
 * Find the bounds of the stack (if any) which includes the
 * specified stack pointer.
 */
void VG_(stack_limits)(Addr SP, Addr *start, Addr *end )
{
   Stack* stack = find_stack_by_addr(SP);

   if (LIKELY(stack)) {
      *start = stack->start;
      *end = stack->end;
   }

   /* 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 stack segment containing SP. */
   Addr stackseg_start, stackseg_end;
   if (UNLIKELY(! VG_(am_stack_limits)(SP, &stackseg_start, &stackseg_end))) {
      VG_(debugLog)(2, "stacks", 
                    "SP %p is not located in a stack segment or stack segment "
                    "has wrong permissions\n", (void*)SP);
      *start = 0;
      *end = 0;
      return;
   } 

   /* 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;
   }

   /* Limit the stack end limit, using the found segment. */
   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;
   }

   /* If reducing start and/or end to the SP segment gives an
      empty range, return 'empty' limits */
   if (UNLIKELY(*start > *end)) {
      VG_(debugLog)(2, "stacks", 
                    "stack for SP %p start %p after end %p\n",
                    (void*)SP, (void*)*start, (void*)end);
      *start = 0;
      *end = 0;
   }
}
Exemplo n.º 3
0
void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP, UInt ecu )
{
   static Int moans = 3;
   Word delta  = (Word)new_SP - (Word)old_SP;

   /* Check if the stack pointer is still in the same stack as before. */
   if (current_stack == NULL ||
       new_SP < current_stack->start || new_SP > current_stack->end) {
      Stack* new_stack = find_stack_by_addr(new_SP);
      if (new_stack 
          && (current_stack == NULL || new_stack->id != current_stack->id)) { 
         /* The stack pointer is now in another stack.  Update the current
            stack information and return without doing anything else. */
         current_stack = new_stack;
         return;
      }
   }

   if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
      /* SP has changed by more than some threshold amount (by
         default, 2MB).  We take this to mean that the application is
         switching to a new stack, for whatever reason.
       
         JRS 20021001: following discussions with John Regehr, if a stack
         switch happens, it seems best not to mess at all with memory
         permissions.  Seems to work well with Netscape 4.X.  Really the
         only remaining difficulty is knowing exactly when a stack switch is
         happening. */
      if (VG_(clo_verbosity) > 0 && moans > 0) {
         moans--;
         VG_(message)(Vg_UserMsg,
            "Warning: client switching stacks?  "
            "SP change: %p --> %p", old_SP, new_SP);
         VG_(message)(Vg_UserMsg,
            "         to suppress, use: --max-stackframe=%ld or greater",
            (delta < 0 ? -delta : delta));
         if (moans == 0)
            VG_(message)(Vg_UserMsg,
                "         further instances of this message "
                "will not be shown.");
      }
   } else if (delta < 0) {
      VG_TRACK( new_mem_stack_w_ECU, new_SP, -delta, ecu );
      VG_TRACK( new_mem_stack,       new_SP, -delta );

   } else if (delta > 0) {
      VG_TRACK( die_mem_stack, old_SP,  delta );
   }
}
Exemplo n.º 4
0
/*
 * Find the bounds of the stack (if any) which includes the
 * specified stack pointer.
 */
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).
      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)) {
      VG_(debugLog)(2, "stacks", 
                    "no addressable segment for SP %p\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)) {
      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;
      }
   }

   /* Limit the stack end limit, using the found segment. */
   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;
   }

   /* If reducing start and/or end to the SP segment gives an
      empty range, return 'empty' limits */
   if (UNLIKELY(*start > *end)) {
      VG_(debugLog)(2, "stacks", 
                    "stack for SP %p start %p after end %p\n",
                    (void*)SP, (void*)*start, (void*)end);
      *start = 0;
      *end = 0;
   }
}