|
From: <sv...@va...> - 2005-09-14 12:56:44
|
Author: sewardj
Date: 2005-09-14 13:56:33 +0100 (Wed, 14 Sep 2005)
New Revision: 4655
Log:
Properly implement VG_(am_notify_mprotect). This increases the number
of programs that actually work. As a side effect, reenable protection
of guard zones at the starts/ends of thread stacks.
Modified:
branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c
branches/ASPACEM/coregrind/pub_core_aspacemgr.h
Modified: branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-14 12:11:3=
7 UTC (rev 4654)
+++ branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-14 12:56:3=
3 UTC (rev 4655)
@@ -1499,6 +1499,11 @@
return res;
}
=20
+static SysRes do_mprotect_NO_NOTIFY(Addr start, SizeT length, UInt prot)
+{
+ return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
+}
+
static SysRes do_munmap_NO_NOTIFY(Addr start, SizeT length)
{
return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
@@ -2485,46 +2490,66 @@
add_segment( &seg );
}
=20
-/* Notifies aspacem that the client completed an mprotect
- successfully. The segment array is updated accordingly. */
+/* Notifies aspacem that an mprotect was completed successfully. The
+ segment array is updated accordingly. Note, as with
+ VG_(am_notify_munmap), it is not the job of this function to reject
+ stupid mprotects, for example the client doing mprotect of
+ non-client areas. Such requests should be intercepted earlier, by
+ the syscall wrapper for mprotect. This function merely records
+ whatever it is told. */
=20
-void VG_(am_notify_client_mprotect)( Addr start, SizeT len, UInt prot )
+void VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot )
{
- Int iLo, iHi;
+ Int i, iLo, iHi;
+ Bool newR, newW, newX;
=20
+ aspacem_assert(VG_IS_PAGE_ALIGNED(start));
+ aspacem_assert(VG_IS_PAGE_ALIGNED(len));
+
if (len =3D=3D 0)
return;
=20
+ split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi );
+
iLo =3D find_nsegment_idx(start);
iHi =3D find_nsegment_idx(start + len - 1);
=20
- if (iLo =3D=3D iHi=20
- && nsegments[iLo].start =3D=3D start=20
- && nsegments[iLo].end+1 =3D=3D start+len
- && (nsegments[iLo].kind =3D=3D SkFileC || nsegments[iLo].kind =3D=
=3D SkAnonC)) {
- nsegments[iLo].hasR =3D toBool(prot & VKI_PROT_READ);
- nsegments[iLo].hasW =3D toBool(prot & VKI_PROT_WRITE);
- nsegments[iLo].hasX =3D toBool(prot & VKI_PROT_EXEC);
- preen_nsegments();
- return;
+ newR =3D toBool(prot & VKI_PROT_READ);
+ newW =3D toBool(prot & VKI_PROT_WRITE);
+ newX =3D toBool(prot & VKI_PROT_EXEC);
+
+ for (i =3D iLo; i <=3D iHi; i++) {
+ /* Apply the permissions to all relevant segments. */
+ switch (nsegments[i].kind) {
+ case SkAnonC: case SkAnonV: case SkFileC: case SkFileV:
+ nsegments[i].hasR =3D newR;
+ nsegments[i].hasW =3D newW;
+ nsegments[i].hasX =3D newX;
+ aspacem_assert(sane_NSegment(&nsegments[i]));
+ break;
+ default:
+ break;
+ }
}
=20
- /* FIXME: unhandled general case */
- if (1)
- VG_(debugLog)(0,"aspacem", "notify mprotect 0x%llx %lld\n",=20
- (ULong)start, (Long)len);
- VG_(am_show_nsegments)(0, "notify_mprotect general case");
- aspacem_barf("notify_mprotect general case");
+ /* Changing permissions could have made previously un-mergable
+ segments mergeable. Therefore have to re-preen them. */
+ preen_segments();
}
=20
=20
-/* Notifies aspacem that the client completed an munmap successfully.
- The segment array is updated accordingly. */
+/* Notifies aspacem that an munmap completed successfully. The
+ segment array is updated accordingly. As with
+ VG_(am_notify_munmap), we merely record the given info, and don't
+ check it for sensibleness. */
=20
-void VG_(am_notify_c_or_v_munmap)( Addr start, SizeT len )
+void VG_(am_notify_munmap)( Addr start, SizeT len )
{
NSegment seg;
=20
+ aspacem_assert(VG_IS_PAGE_ALIGNED(start));
+ aspacem_assert(VG_IS_PAGE_ALIGNED(len));
+
if (len =3D=3D 0)
return;
=20
@@ -2533,6 +2558,10 @@
seg.start =3D start;
seg.end =3D start + len - 1;
add_segment( &seg );
+
+ /* Unmapping could create two adjacent free segments, so a preen is
+ needed. */
+ preen_segments();
}
=20
=20
@@ -2824,7 +2853,8 @@
=20
init_nsegment( &seg );
seg.kind =3D SkResvn;
- seg.start =3D start1; /* NB: extra space is not included in the rese=
rvation. */
+ seg.start =3D start1; /* NB: extra space is not included in the
+ reservation. */
seg.end =3D end1;
seg.smode =3D smode;
add_segment( &seg );
@@ -2963,27 +2993,26 @@
aspacem_assert(VG_IS_PAGE_ALIGNED(stack));
=20
/* Protect the guard areas. */
-#if 0
sres =3D do_mprotect_NO_NOTIFY(=20
- &stack[0],=20
+ (Addr) &stack[0],=20
VG_STACK_GUARD_SZB, VKI_PROT_NONE=20
);
if (sres.isError) goto protect_failed;
- VG_(am_notify_valgrind_mprotect)(=20
- &stack[0],=20
+ VG_(am_notify_mprotect)(=20
+ (Addr) &stack->bytes[0],=20
VG_STACK_GUARD_SZB, VKI_PROT_NONE=20
);
=20
sres =3D do_mprotect_NO_NOTIFY(=20
- &stack[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB],=20
+ (Addr) &stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_S=
ZB],=20
VG_STACK_GUARD_SZB, VKI_PROT_NONE=20
);
if (sres.isError) goto protect_failed;
- VG_(am_notify_valgrind_mprotect)(=20
- &stack[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB],
+ VG_(am_notify_mprotect)(=20
+ (Addr) &stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB],
VG_STACK_GUARD_SZB, VKI_PROT_NONE=20
);
-#endif
+
/* Looks good. Fill the active area with junk so we can later
tell how much got used. */
=20
@@ -2998,13 +3027,12 @@
VG_(debugLog)( 1,"aspacem","allocated thread stack at 0x%llx size %d\=
n",
(ULong)(Addr)stack, szB);
return stack;
-#if 0
+
protect_failed:
/* The stack was allocated, but we can't protect it. Unmap it and
return NULL (failure). */
(void)do_munmap_NO_NOTIFY( (Addr)stack, szB );
return NULL;
-#endif
}
=20
=20
Modified: branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c 2005-09-14 12:=
11:37 UTC (rev 4654)
+++ branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c 2005-09-14 12:=
56:33 UTC (rev 4655)
@@ -4641,7 +4641,7 @@
Bool xx =3D toBool(prot & VKI_PROT_EXEC);
=20
page_align_addr_and_len(&a, &len);
- VG_(am_notify_client_mprotect)(a, len, prot);
+ VG_(am_notify_mprotect)(a, len, prot);
VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
}
=20
@@ -4661,7 +4661,7 @@
SizeT len =3D ARG2;
=20
page_align_addr_and_len(&a, &len);
- VG_(am_notify_c_or_v_munmap)(a, len);
+ VG_(am_notify_munmap)(a, len);
VG_TRACK( die_mem_munmap, a, len );
}
=20
Modified: branches/ASPACEM/coregrind/pub_core_aspacemgr.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/pub_core_aspacemgr.h 2005-09-14 12:11:37 U=
TC (rev 4654)
+++ branches/ASPACEM/coregrind/pub_core_aspacemgr.h 2005-09-14 12:56:33 U=
TC (rev 4655)
@@ -302,21 +302,27 @@
extern void VG_(am_notify_client_mmap)
( Addr a, SizeT len, UInt prot, UInt flags, Int fd, SizeT offset );
=20
-/* Notifies aspacem that the client completed an mprotect
- successfully. The segment array is updated accordingly. */
-extern void VG_(am_notify_client_mprotect)( Addr a, SizeT len, UInt prot=
);
+/* Notifies aspacem that an mprotect was completed successfully. The
+ segment array is updated accordingly. Note, as with
+ VG_(am_notify_munmap), it is not the job of this function to reject
+ stupid mprotects, for example the client doing mprotect of
+ non-client areas. Such requests should be intercepted earlier, by
+ the syscall wrapper for mprotect. This function merely records
+ whatever it is told. */
+extern void VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot );
=20
-/* Notifies aspacem that an munmap was completed successfully. This
- can be used to unmap either client or Valgrind areas. The segment
- array is updated accordingly. */
-extern void VG_(am_notify_c_or_v_munmap)( Addr start, SizeT len );
+/* Notifies aspacem that an munmap completed successfully. The
+ segment array is updated accordingly. As with
+ VG_(am_notify_munmap), we merely record the given info, and don't
+ check it for sensibleness. */
+extern void VG_(am_notify_munmap)( Addr start, SizeT len );
=20
=20
/* Hand a raw mmap to the kernel, without aspacem updating the segment
array. THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
of the address space to diverge from that of the kernel. DO NOT
USE IT UNLESS YOU UNDERSTAND the request-notify model used by
- aspacem. */
+ aspacem. In short, DO NOT USE THIS FUNCTION. */
extern SysRes VG_(am_do_mmap_NO_NOTIFY)
( Addr start, SizeT length, UInt prot, UInt flags, UInt fd, OffT offs=
et);
=20
|