Change VG_(am_extend_map_client) as follows:
- Tighten up on asserts
- Simplify; as the function grows memory into a free segment, there
  cannot possibly be any translations to be discarded. Free segments
  do not have translations. sane_NSegment will make sure.
- Change the prototype to take in the start address of the mapping and
  return a pointer to the resized segment. Previously, the code 

   ok = VG_(am_extend_map_client)( &d, old_seg, needL );
   if (!ok)
      goto eNOMEM;
   VG_TRACK( new_mem_mmap, needA, needL, 
                           old_seg->hasR, old_seg->hasW, old_seg->hasX,

  was examining old_seg->hasR etc even though VG_(am_extend_map_client)
  stated that *old_seg was invalid after the function returned.
  That wasn't exactly a problem, but clearly looked wrong.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14963 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c
index 41fb3e4..32ac842 100644
--- a/coregrind/m_aspacemgr/aspacemgr-linux.c
+++ b/coregrind/m_aspacemgr/aspacemgr-linux.c
@@ -2892,38 +2892,38 @@
 
 #if HAVE_MREMAP
 
-/* Let SEG be a client mapping (anonymous or file).  This fn extends
-   the mapping forwards only by DELTA bytes, and trashes whatever was
-   in the new area.  Fails if SEG is not a single client mapping or if
-   the new area is not accessible to the client.  Fails if DELTA is
-   not page aligned.  *seg is invalid after a successful return.  If
-   *need_discard is True after a successful return, the caller should
-   immediately discard translations from the new area. */
-
-Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard,
-                                const NSegment* seg, SizeT delta )
+/* This function grows a client mapping in place into an adjacent free segment.
+   ADDR is the client mapping's start address and DELTA, which must be page
+   aligned, is the growth amount. The function returns a pointer to the
+   resized segment. The function is used in support of mremap. */
+const NSegment *VG_(am_extend_map_client)( Addr addr, SizeT delta )
 {
    Addr     xStart;
    SysRes   sres;
-   NSegment seg_copy = *seg;
-   SizeT    seg_old_len = seg->end + 1 - seg->start;
 
    if (0)
       VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) BEFORE");
 
-   if (seg->kind != SkFileC && seg->kind != SkAnonC)
-      return False;
+   /* Get the client segment */
+   Int ix = find_nsegment_idx(addr);
+   aspacem_assert(ix >= 0 && ix < nsegments_used);
 
-   if (delta == 0 || !VG_IS_PAGE_ALIGNED(delta)) 
-      return False;
+   NSegment *seg = nsegments + ix;
+
+   aspacem_assert(seg->kind == SkFileC || seg->kind == SkAnonC);
+   aspacem_assert(delta > 0 && VG_IS_PAGE_ALIGNED(delta)) ;
 
    xStart = seg->end+1;
-   if (xStart + delta < delta)
-      return False;
+   aspacem_assert(xStart + delta >= delta);   // no wrap-around
 
-   if (!VG_(am_is_valid_for_client_or_free_or_resvn)( xStart, delta, 
-                                                      VKI_PROT_NONE ))
-      return False;
+   /* The segment following the client segment must be a free segment and
+      it must be large enough to cover the additional memory. */
+   NSegment *segf = seg + 1;
+   aspacem_assert(segf->kind == SkFree);
+   aspacem_assert(segf->start == xStart);
+   aspacem_assert(xStart + delta - 1 <= segf->end);
+
+   SizeT seg_old_len = seg->end + 1 - seg->start;
 
    AM_SANITY_CHECK;
    sres = ML_(am_do_extend_mapping_NO_NOTIFY)( seg->start, 
@@ -2931,14 +2931,13 @@
                                                seg_old_len + delta );
    if (sr_isError(sres)) {
       AM_SANITY_CHECK;
-      return False;
+      return NULL;
    } else {
       /* the area must not have moved */
       aspacem_assert(sr_Res(sres) == seg->start);
    }
 
-   *need_discard = any_Ts_in_range( seg_copy.end+1, delta );
-
+   NSegment seg_copy = *seg;
    seg_copy.end += delta;
    add_segment( &seg_copy );
 
@@ -2946,7 +2945,7 @@
       VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) AFTER");
 
    AM_SANITY_CHECK;
-   return True;
+   return nsegments + find_nsegment_idx(addr);
 }
 
 
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index 42d134c..eaf29d0 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -435,14 +435,12 @@
       ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
    }
    if (ok && advised == needA) {
-      ok = VG_(am_extend_map_client)( &d, old_seg, needL );
-      if (ok) {
+      const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
+      if (new_seg) {
          VG_TRACK( new_mem_mmap, needA, needL, 
-                                 old_seg->hasR, 
-                                 old_seg->hasW, old_seg->hasX,
+                                 new_seg->hasR, 
+                                 new_seg->hasW, new_seg->hasX,
                                  0/*di_handle*/ );
-         if (d) 
-            VG_(discard_translations)( needA, needL, "do_remap(3)" );
          return VG_(mk_SysRes_Success)( old_addr );
       }
    }
@@ -490,14 +488,13 @@
    }
    if (!ok || advised != needA)
       goto eNOMEM;
-   ok = VG_(am_extend_map_client)( &d, old_seg, needL );
-   if (!ok)
+   const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
+   if (!new_seg)
       goto eNOMEM;
    VG_TRACK( new_mem_mmap, needA, needL, 
-                           old_seg->hasR, old_seg->hasW, old_seg->hasX,
+                           new_seg->hasR, new_seg->hasW, new_seg->hasX,
                            0/*di_handle*/ );
-   if (d)
-      VG_(discard_translations)( needA, needL, "do_remap(6)" );
+
    return VG_(mk_SysRes_Success)( old_addr );
    }
    /*NOTREACHED*/ vg_assert(0);
diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h
index 915c37a..7db4141 100644
--- a/coregrind/pub_core_aspacemgr.h
+++ b/coregrind/pub_core_aspacemgr.h
@@ -286,15 +286,11 @@
 
 /* --- --- --- resizing/move a mapping --- --- --- */
 
-/* Let SEG be a client mapping (anonymous or file).  This fn extends
-   the mapping forwards only by DELTA bytes, and trashes whatever was
-   in the new area.  Fails if SEG is not a single client mapping or if
-   the new area is not accessible to the client.  Fails if DELTA is
-   not page aligned.  *seg is invalid after a successful return.  If
-   *need_discard is True after a successful return, the caller should
-   immediately discard translations from the new area. */
-extern Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard,
-                                       const NSegment* seg, SizeT delta );
+/* This function grows a client mapping in place into an adjacent free segment.
+   ADDR is the client mapping's start address and DELTA, which must be page
+   aligned, is the growth amount. The function returns a pointer to the
+   resized segment. The function is used in support of mremap. */
+extern const NSegment *VG_(am_extend_map_client)( Addr addr, SizeT delta );
 
 /* Remap the old address range to the new address range.  Fails if any
    parameter is not page aligned, if the either size is zero, if any