|
From: <sv...@va...> - 2005-09-12 02:40:30
|
Author: sewardj
Date: 2005-09-12 03:40:24 +0100 (Mon, 12 Sep 2005)
New Revision: 4622
Log:
Use shrinkable reservation infrastructure to reimplement
segfault-based stack growth.
Modified:
branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
branches/ASPACEM/coregrind/m_main.c
branches/ASPACEM/coregrind/m_signals.c
branches/ASPACEM/coregrind/m_transtab.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-12 00:56:1=
4 UTC (rev 4621)
+++ branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-12 02:40:2=
4 UTC (rev 4622)
@@ -1489,7 +1489,7 @@
Int i;
if (seg < &nsegments[0] || seg >=3D &nsegments[nsegments_used])
return -1;
- i =3D (seg - &nsegments[0]) / sizeof(NSegment);
+ i =3D ((UChar*)seg - (UChar*)(&nsegments[0])) / sizeof(NSegment);
if (i < 0 || i >=3D nsegments_used)
return -1;
if (seg =3D=3D &nsegments[i])
@@ -1497,7 +1497,31 @@
return -1;
}
=20
+/* Find the next segment along from HERE, if it is a file/anon/resvn
+ segment. */
+NSegment* VG_(next_nsegment) ( NSegment* here, Bool fwds )
+{
+ Int i =3D segAddr_to_index(here);
+ if (i < 0 || i >=3D nsegments_used)
+ return NULL;
+ if (fwds) {
+ i++;
+ if (i >=3D nsegments_used)
+ return NULL;
+ } else {
+ i--;
+ if (i < 0)
+ return NULL;
+ }
+ if (nsegments[i].kind =3D=3D SkFile=20
+ || nsegments[i].kind =3D=3D SkAnon
+ || nsegments[i].kind =3D=3D SkResvn)
+ return &nsegments[i];
+ else=20
+ return NULL;
+}
=20
+
ULong VG_(aspacem_get_anonsize_total)( void )
{
Int i;
@@ -2343,9 +2367,9 @@
if (extra > 0) end2 +=3D extra;
=20
aspacem_assert(VG_IS_PAGE_ALIGNED(start));
- aspacem_assert(VG_IS_PAGE_ALIGNED(start+length-1));
+ aspacem_assert(VG_IS_PAGE_ALIGNED(start+length));
aspacem_assert(VG_IS_PAGE_ALIGNED(start2));
- aspacem_assert(VG_IS_PAGE_ALIGNED(end2));
+ aspacem_assert(VG_IS_PAGE_ALIGNED(end2+1));
=20
startI =3D find_nsegment_idx( start2 );
endI =3D find_nsegment_idx( end2 );
Modified: branches/ASPACEM/coregrind/m_main.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_main.c 2005-09-12 00:56:14 UTC (rev 4621=
)
+++ branches/ASPACEM/coregrind/m_main.c 2005-09-12 02:40:24 UTC (rev 4622=
)
@@ -484,11 +484,13 @@
space manager. A modified version of our auxv is copied into the
new stack. The returned value is the SP value for the client. */
static=20
-Addr setup_client_stack( void* init_sp,
- char **orig_argv, char **orig_envp,=20
+Addr setup_client_stack( void* init_sp,
+ char** orig_argv,=20
+ char** orig_envp,=20
const struct exeinfo *info,
UInt** client_auxv,
- Addr clstack_end )
+ Addr clstack_end,
+ SizeT clstack_max_size )
{
SysRes res;
char **cpp;
@@ -576,23 +578,51 @@
=20
clstack_start =3D VG_PGROUNDDN(client_SP);
=20
+ /* The max stack size */
+ clstack_max_size =3D VG_PGROUNDUP(clstack_max_size);
+
if (0)
- VG_(printf)("stringsize=3D%d auxsize=3D%d stacksize=3D%d\n"
+ VG_(printf)("stringsize=3D%d auxsize=3D%d stacksize=3D%d maxsize=3D=
0x%x\n"
"clstack_start %p\n"
"clstack_end %p\n",
- stringsize, auxsize, stacksize,
+ stringsize, auxsize, stacksize, (Int)clstack_max_size,
(void*)clstack_start, (void*)clstack_end);
=20
/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D alloc=
ate space =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
=20
- /* allocate a stack - mmap enough space for the stack */
- res =3D VG_(mmap_anon_fixed_client)(
- (void *)clstack_start -40960,
- clstack_end - clstack_start + 1 +40960,
- VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
- );
- vg_assert(!res.isError);=20
+ { SizeT anon_size =3D clstack_end - clstack_start + 1;
+ SizeT resvn_size =3D clstack_max_size - anon_size;
+ Addr anon_start =3D clstack_start;
+ Addr resvn_start =3D anon_start - resvn_size;
=20
+ vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
+ vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
+ vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
+ vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
+ vg_assert(resvn_start =3D clstack_end + 1 - clstack_max_size);
+
+ if (0)
+ VG_(printf)("%p 0x%x %p 0x%x\n",=20
+ resvn_start, resvn_size, anon_start, anon_size);
+
+ /* Create a shrinkable reservation followed by an anonymous
+ segment. Together these constitute a growdown stack. */
+ Bool ok =3D VG_(create_reservation)(
+ resvn_start,
+ resvn_size,
+ SmUpper,=20
+ anon_size
+ );
+ vg_assert(ok);
+ /* allocate a stack - mmap enough space for the stack */
+ res =3D VG_(mmap_anon_fixed_client)(
+ (void*)anon_start,
+ anon_size,
+ VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
+ );
+ vg_assert(!res.isError);=20
+ }
+
/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D copy =
client stack =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
*/
=20
ptr =3D (Addr*)client_SP;
@@ -820,6 +850,7 @@
}
}
=20
+ VG_(memset)(info, 0, sizeof(*info));
info->map_base =3D VG_(client_mapbase);
info->exe_base =3D VG_(client_base);
info->exe_end =3D VG_(client_end);
@@ -827,8 +858,6 @@
=20
if (need_help) {
VG_(clexecfd) =3D -1;
- // Totally zero 'info' before continuing.
- VG_(memset)(info, 0, sizeof(*info));
} else {
Int ret;
/* HACK: assumes VG_(open) always succeeds */
@@ -2239,9 +2268,16 @@
VG_(debugLog)(1, "main", "Setup client stack\n");
{ void* init_sp =3D argv - 1;
=20
+ SizeT one_meg =3D 1024 * 1024;
+ SizeT eight_megs =3D 8 * one_meg;
+ SizeT stack_max_size =3D (SizeT)VG_(client_rlimit_stack).rlim_cur;
+ if (stack_max_size < one_meg) stack_max_size =3D one_meg;
+ if (stack_max_size > eight_megs) stack_max_size =3D eight_megs;
+
initial_client_SP
- =3D setup_client_stack(init_sp, cl_argv, env, &info,
- &client_auxv,clstack_top);
+ =3D setup_client_stack( init_sp, cl_argv, env, &info,
+ &client_auxv, clstack_top, stack_max_size=
);
+
VG_(free)(env);
}
=20
Modified: branches/ASPACEM/coregrind/m_signals.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_signals.c 2005-09-12 00:56:14 UTC (rev 4=
621)
+++ branches/ASPACEM/coregrind/m_signals.c 2005-09-12 02:40:24 UTC (rev 4=
622)
@@ -80,6 +80,7 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_debuglog.h"
#include "pub_core_threadstate.h"
#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
#include "pub_core_aspacemgr.h"
@@ -1701,66 +1702,43 @@
*/
Bool VG_(extend_stack)(Addr addr, UInt maxsize)
{
- Segment *seg;
- Addr base;
- UInt newsize;
+ SizeT udelta;
=20
/* Find the next Segment above addr */
- seg =3D VG_(find_segment)(addr);
- if (seg)
+ NSegment* seg =3D VG_(find_nsegment)(addr);
+ NSegment* seg_next =3D seg ? VG_(next_nsegment)( seg, True/*fwds*/ ) =
: NULL;
+
+ if (seg && seg->kind =3D=3D SkAnon)
+ /* addr is already mapped. Nothing to do. */
return True;
=20
- /* now we know addr is definitely unmapped */
- seg =3D VG_(find_segment_above_unmapped)(addr);
-
- /* If there isn't one, or it isn't growable, fail */
- if (seg =3D=3D NULL ||=20
- !(seg->flags & SF_GROWDOWN) ||
- VG_(seg_contains)(seg, addr, sizeof(void *)))
+ /* Check that the requested new base is in a shrink-down
+ reservation section which abuts an anonymous mapping that
+ belongs to the client. */
+ if ( ! (seg
+ && seg->kind =3D=3D SkResvn
+ && seg->smode =3D=3D SmUpper
+ && seg_next
+ && seg_next->kind =3D=3D SkAnon
+ && seg_next->isClient
+ && seg->end+1 =3D=3D seg_next->start))
return False;
- =20
- vg_assert(seg->addr > addr);
=20
- /* Create the mapping */
- base =3D VG_PGROUNDDN(addr);
- newsize =3D seg->addr - base;
-
- if (seg->len + newsize >=3D maxsize)
+ udelta =3D VG_PGROUNDUP(seg_next->start - addr);
+ VG_(debugLog)(1, "signals",=20
+ "extending a stack base 0x%llx down by %lld ..\n",
+ (ULong)seg_next->start, (ULong)udelta);
+ if (! VG_(extend_into_adjacent_reservation)( seg_next, -(SSizeT)udelt=
a )) {
+ VG_(debugLog)(1, "signals", " .. failure\n");
return False;
+ }
=20
- /* Nasty Hack. The new segment will have SF_MMAP set because
- that's what VG_(mmap) does. But the existing stack segment
- won't necessarily have it set, because the initial segment list
- entry for the main thread's stack doesn't have it set. That
- means that the segment list preener won't merge the segments
- together (because they have different flags). That means the
- segment list will in fact list two adjacent segments for the
- main stack, which is wrong. This means that the tests which
- check if a translation is from a stack-like area and therefore
- in need of a self-check will not work right. Sigh.
+ VG_(debugLog)(1, "signals", " .. success\n");
=20
- So .. in lieu of fixing this properly (viz, rationalising all
- the SF_ flags), just mark the original stack segment as having
- SF_MMAP. Then the preener will merge it into the new area.
- This is a hack. */
- seg->flags |=3D SF_MMAP;
- /* end of Nasty Hack */
-
- if (VG_(mmap)((Char *)base, newsize,
- seg->prot,
- VKI_MAP_PRIVATE | VKI_MAP_FIXED | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
- seg->flags,
- -1, 0) =3D=3D (void *)-1)
- return False;
-
/* When we change the main stack, we have to let the stack handling
code know about it. */
- VG_(change_stack)(VG_(clstk_id), base, VG_(clstk_end));
+ /// FIXME VG_(change_stack)(VG_(clstk_id), base, VG_(clstk_end));
=20
- if (0)
- VG_(printf)("extended stack: %p %d\n",
- base, newsize);
-
if (VG_(clo_sanity_level) > 2)
VG_(sanity_check_general)(False);
=20
@@ -1855,7 +1833,8 @@
}=20
=20
if (VG_(clo_trace_signals)) {
- VG_(message)(Vg_DebugMsg, "signal %d arrived ... si_code=3D%d, EIP=
=3D%p, eip=3D%p",
+ VG_(message)(Vg_DebugMsg, "signal %d arrived ... si_code=3D%d, "
+ "EIP=3D%p, eip=3D%p",
sigNo, info->si_code, VG_(get_IP)(tid),=20
VG_UCONTEXT_INSTR_PTR(uc) );
}
@@ -1867,27 +1846,32 @@
if (info->si_signo =3D=3D VKI_SIGSEGV) {
Addr fault =3D (Addr)info->_sifields._sigfault._addr;
Addr esp =3D VG_(get_SP)(tid);
- Segment* seg;
+ NSegment* seg =3D VG_(find_nsegment)(fault);
+ NSegment* seg_next =3D seg ? VG_(next_nsegment)( seg, True/*fwds*/=
) : NULL;
=20
- seg =3D VG_(find_segment)(fault);
- if (seg =3D=3D NULL)
- seg =3D VG_(find_segment_above_unmapped)(fault);
-
if (VG_(clo_trace_signals)) {
if (seg =3D=3D NULL)
VG_(message)(Vg_DebugMsg,
- "SIGSEGV: si_code=3D%d faultaddr=3D%p tid=3D%d ESP=3D%p seg=3DNULL s=
had=3D%p-%p",
+ "SIGSEGV: si_code=3D%d faultaddr=3D%p tid=3D%d ESP=3D%p "
+ "seg=3DNULL shad=3D%p-%p",
info->si_code, fault, tid, esp,
VG_(shadow_base), VG_(shadow_end));
else
VG_(message)(Vg_DebugMsg,
- "SIGSEGV: si_code=3D%d faultaddr=3D%p tid=3D%d ESP=3D%p seg=3D%p-%p =
fl=3D%x shad=3D%p-%p",
- info->si_code, fault, tid, esp, seg->addr, seg->addr+seg->len, seg->=
flags,
- VG_(shadow_base), VG_(shadow_end));
+ "SIGSEGV: si_code=3D%d faultaddr=3D%p tid=3D%d ESP=3D%p "
+ "seg=3D%p-%p shad=3D%p-%p",
+ info->si_code, fault, tid, esp, seg->start, seg->end,=20
+ VG_(shadow_base), VG_(shadow_end));
}
if (info->si_code =3D=3D 1 /* SEGV_MAPERR */
- && fault >=3D (esp - VG_STACK_REDZONE_SZB)
- && fault < VG_(client_end)) {
+ && seg
+ && seg->kind =3D=3D SkResvn
+ && seg->smode =3D=3D SmUpper
+ && seg_next
+ && seg_next->kind =3D=3D SkAnon
+ && seg_next->isClient
+ && seg->end+1 =3D=3D seg_next->start
+ && fault >=3D (esp - VG_STACK_REDZONE_SZB)) {
/* If the fault address is above esp but below the current known
stack segment base, and it was a fault because there was
nothing mapped there (as opposed to a permissions fault),
@@ -1897,10 +1881,12 @@
if (VG_(extend_stack)(base, VG_(threads)[tid].client_stack_szB)) {
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugMsg,=20
- " -> extended stack base to %p", VG_PGROUNDDN(fault));
- return; // extension succeeded, restart instruction
+ " -> extended stack base to %p",=20
+ VG_PGROUNDDN(fault));
+ return; // extension succeeded, restart instruction
} else
- VG_(message)(Vg_UserMsg, "Stack overflow in thread %d: can't grow s=
tack to %p",=20
+ VG_(message)(Vg_UserMsg,=20
+ "Stack overflow in thread %d: can't grow stack =
to %p",=20
tid, fault);
}
/* Fall into normal signal handling for all other cases */
Modified: branches/ASPACEM/coregrind/m_transtab.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_transtab.c 2005-09-12 00:56:14 UTC (rev =
4621)
+++ branches/ASPACEM/coregrind/m_transtab.c 2005-09-12 02:40:24 UTC (rev =
4622)
@@ -312,7 +312,7 @@
8 * tc_sector_szQ );
/*NOTREACHED*/
}
- sectors[sno].tc =3D sres.val;
+ sectors[sno].tc =3D (ULong*)sres.val;
=20
sres =3D VG_(map_anon_float_valgrind)( N_TTES_PER_SECTOR * sizeof(=
TTEntry) );
if (sres.isError) {
@@ -320,7 +320,7 @@
N_TTES_PER_SECTOR * sizeof(TTEntry)=
);
/*NOTREACHED*/
}
- sectors[sno].tt =3D sres.val;
+ sectors[sno].tt =3D (TTEntry*)sres.val;
=20
if (VG_(clo_verbosity) > 2)
VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d", sno);
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-12 00:56:14 U=
TC (rev 4621)
+++ branches/ASPACEM/coregrind/pub_core_aspacemgr.h 2005-09-12 02:40:24 U=
TC (rev 4622)
@@ -269,7 +269,12 @@
=20
extern SysRes VG_(munmap_client)( Addr base, SizeT length );
=20
+/* Finds the segment containing 'a'. Only returns file/anon/resvn
+ segments. */
extern NSegment* VG_(find_nsegment) ( Addr a );
+
+/* Find the next segment along from HERE, if it is a file/anon/resvn
+ segment. */
extern NSegment* VG_(next_nsegment) ( NSegment* here, Bool fwds );
=20
/* Create a reservation from START .. START+LENGTH-1, with the given
|