diff options
author | iraisr <iraisr@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2015-08-22 22:08:43 +0000 |
---|---|---|
committer | iraisr <iraisr@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2015-08-22 22:08:43 +0000 |
commit | bcfaeedb1e1ac2625eea81951a785a777834321c (patch) | |
tree | 71933b69a25b270b1cf972bbf4c7279946773901 /coregrind | |
parent | 913b580c090c25766cafd77a19993f89fb1271e3 (diff) | |
download | valgrind-bcfaeedb1e1ac2625eea81951a785a777834321c.tar.gz |
Distinguish properly when to establish the client data segment.
Initial data segment is established (see initimg-solaris.c for rationale):
- directly during client program image initialization,
- or on demand when the executed program is the runtime linker itself,
after it has loaded its target dynamic executable (see PRE(sys_mmapobj)),
or when the first brk() syscall is made.
More preparatory work for ldsoexec support.
n-i-bz
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15583 a5019735-40e9-0310-863c-91ae7b9d1cf9
Diffstat (limited to 'coregrind')
-rw-r--r-- | coregrind/m_initimg/initimg-solaris.c | 38 | ||||
-rw-r--r-- | coregrind/m_syswrap/syswrap-solaris.c | 64 | ||||
-rw-r--r-- | coregrind/m_ume/elf.c | 8 | ||||
-rw-r--r-- | coregrind/pub_core_syswrap.h | 2 | ||||
-rw-r--r-- | coregrind/pub_core_ume.h | 1 |
5 files changed, 73 insertions, 40 deletions
diff --git a/coregrind/m_initimg/initimg-solaris.c b/coregrind/m_initimg/initimg-solaris.c index 20b02d18a..bdfb6c545 100644 --- a/coregrind/m_initimg/initimg-solaris.c +++ b/coregrind/m_initimg/initimg-solaris.c @@ -48,6 +48,7 @@ #include "pub_core_machine.h" #include "pub_core_ume.h" #include "pub_core_options.h" +#include "pub_core_syswrap.h" #include "pub_core_tooliface.h" /* VG_TRACK */ #include "pub_core_threadstate.h" /* ThreadArchState */ #include "priv_initimg_pathscan.h" @@ -102,7 +103,11 @@ static void load_client(/*OUT*/ExeInfo *info, VG_(cl_exec_fd) = sr_Res(res); /* Set initial brk values. */ - VG_(brk_base) = VG_(brk_limit) = info->brkbase; + if (info->ldsoexec) { + VG_(brk_base) = VG_(brk_limit) = -1; + } else { + VG_(brk_base) = VG_(brk_limit) = info->brkbase; + } } @@ -841,10 +846,20 @@ IIFinaliseImageInfo VG_(ii_create_image)(IICreateImageInfo iicii, iifii.clstack_max_size); } - /* Initial data (brk) segment is setup on demand, when a first brk() syscall - is made. It cannot be established now because it would conflict with - a temporary stack which ld.so.1 (when executed directly) uses for loading - the target dynamic executable. See PRE(sys_brk) in syswrap-solaris.c. */ + if (info.ldsoexec) { + /* We are executing the runtime linker itself. + Initial data (brk) segment is setup on demand, after the target dynamic + executable has been loaded or when a first brk() syscall is made. + It cannot be established now because it would conflict with a temporary + stack which ld.so.1 (when executed directly) uses for loading the + target dynamic executable. See PRE(sys_brk) in syswrap-solaris.c. */ + } else { + if (!VG_(setup_client_dataseg)()) { + VG_(printf)("valgrind: cannot initialize data segment (brk).\n"); + VG_(exit)(1); + } + } + return iifii; } @@ -916,15 +931,10 @@ void VG_(ii_finalise_image)(IIFinaliseImageInfo iifii) VG_TRACK(post_reg_write, Vg_CoreStartup, 1/*tid*/, 0/*offset*/, sizeof(VexGuestArchState)); - /* Make inaccessible/unaddressable the end of the client data segment. - See PRE(sys_brk) in syswrap-solaris.c for details. Nothing to do in - case VG_(brk_base) starts on the beginning of a free page. */ - const NSegment *seg = VG_(am_find_nsegment)(VG_(brk_base)); - if (seg != NULL) { - vg_assert((seg->kind == SkFileC) || (seg->kind == SkAnonC)); - VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base), - 1 /* tid */); - VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base)); + if (VG_(brk_base) != -1 ) { + /* Make inaccessible/unaddressable the end of the client data segment. + See PRE(sys_brk) in syswrap-solaris.c for details. */ + VG_(track_client_dataseg)(1 /* tid */); } } diff --git a/coregrind/m_syswrap/syswrap-solaris.c b/coregrind/m_syswrap/syswrap-solaris.c index 4ea2463f4..54ad280f8 100644 --- a/coregrind/m_syswrap/syswrap-solaris.c +++ b/coregrind/m_syswrap/syswrap-solaris.c @@ -1806,8 +1806,13 @@ PRE(sys_time) /* Data segment for brk (heap). It is an expandable anonymous mapping abutting a 1-page reservation. The data segment starts at VG_(brk_base) and runs up to VG_(brk_limit). None of these two values have to be - page-aligned. Initial data segment is established on demand here (see - initimg-solaris.c for rationale). + page-aligned. + Initial data segment is established (see initimg-solaris.c for rationale): + - directly during client program image initialization, + - or on demand when the executed program is the runtime linker itself, + after it has loaded its target dynamic executable (see PRE(sys_mmapobj)), + or when the first brk() syscall is made. + Notable facts: - VG_(brk_base) is not page aligned; does not move - VG_(brk_limit) moves between [VG_(brk_base), data segment end] @@ -1838,9 +1843,23 @@ PRE(sys_time) The page that contains VG_(brk_base) is already allocated by the program's loaded data segment. The brk syscall wrapper handles this special case. */ +static Bool brk_segment_established = False; + /* Establishes initial data segment for brk (heap). */ -static Bool setup_client_dataseg(SizeT initial_size, ThreadId tid) -{ +Bool VG_(setup_client_dataseg)(void) +{ + /* Segment size is initially at least 1 MB and at most 8 MB. */ + SizeT m1 = 1024 * 1024; + SizeT m8 = 8 * m1; + SizeT initial_size = VG_(client_rlimit_data).rlim_cur; + VG_(debugLog)(1, "syswrap-solaris", "Setup client data (brk) segment " + "at %#lx\n", VG_(brk_base)); + if (initial_size < m1) + initial_size = m1; + if (initial_size > m8) + initial_size = m8; + initial_size = VG_PGROUNDUP(initial_size); + Addr anon_start = VG_PGROUNDUP(VG_(brk_base)); SizeT anon_size = VG_PGROUNDUP(initial_size); Addr resvn_start = anon_start + anon_size; @@ -1873,18 +1892,22 @@ static Bool setup_client_dataseg(SizeT initial_size, ThreadId tid) vg_assert(!sr_isError(sres)); vg_assert(sr_Res(sres) == anon_start); - /* Tell the tool about the client data segment and then kill it which will - make it initially inaccessible/unaddressable. */ - seg = VG_(am_find_nsegment)(anon_start); + brk_segment_established = True; + return True; +} + +/* Tell the tool about the client data segment and then kill it which will + make it initially inaccessible/unaddressable. */ +void VG_(track_client_dataseg)(ThreadId tid) +{ + const NSegment *seg = VG_(am_find_nsegment)(VG_PGROUNDUP(VG_(brk_base))); vg_assert(seg != NULL); vg_assert(seg->kind == SkAnonC); + VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base), tid); VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base)); - return True; } -static Bool brk_segment_established = False; - PRE(sys_brk) { /* unsigned long brk(caddr_t end_data_segment); */ @@ -1923,31 +1946,22 @@ PRE(sys_brk) return; } + /* The brk base and limit must have been already set. */ + vg_assert(VG_(brk_base) != -1); + vg_assert(VG_(brk_limit) != -1); + if (!brk_segment_established) { /* Stay sane (because there should have been no brk activity yet). */ vg_assert(VG_(brk_base) == VG_(brk_limit)); - /* Establish an initial data segment for brk (heap). - Initially at least 1 MB and at most 8 MB large. */ - SizeT m1 = 1024 * 1024; - SizeT m8 = 8 * m1; - SizeT dseg_max_size = VG_(client_rlimit_data).rlim_cur; - VG_(debugLog)(1, "syswrap-solaris", "Setup client data (brk) segment " - "at %#lx\n", VG_(brk_base)); - if (dseg_max_size < m1) - dseg_max_size = m1; - if (dseg_max_size > m8) - dseg_max_size = m8; - dseg_max_size = VG_PGROUNDUP(dseg_max_size); - - if (!setup_client_dataseg(dseg_max_size, tid)) { + if (!VG_(setup_client_dataseg)()) { VG_(umsg)("Cannot map memory to initialize brk segment in thread #%d " "at %#lx\n", tid, VG_(brk_base)); SET_STATUS_Failure(VKI_ENOMEM); return; } - brk_segment_established = True; + VG_(track_client_dataseg)(tid); } if (new_brk < old_brk_limit) { diff --git a/coregrind/m_ume/elf.c b/coregrind/m_ume/elf.c index 78a22f2b9..a9871501f 100644 --- a/coregrind/m_ume/elf.c +++ b/coregrind/m_ume/elf.c @@ -563,9 +563,15 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info) VG_(free)(interp->p); VG_(free)(interp); - } else + } else { entry = (void *)(ebase + e->e.e_entry); +# if defined(VGO_solaris) + if (e->e.e_type == ET_DYN) + info->ldsoexec = True; +# endif + } + info->exe_base = minaddr + ebase; info->exe_end = maxaddr + ebase; diff --git a/coregrind/pub_core_syswrap.h b/coregrind/pub_core_syswrap.h index 2508b28c0..35e8bc915 100644 --- a/coregrind/pub_core_syswrap.h +++ b/coregrind/pub_core_syswrap.h @@ -93,6 +93,8 @@ extern void VG_(save_context)(ThreadId tid, vki_ucontext_t *uc, extern void VG_(restore_context)(ThreadId tid, vki_ucontext_t *uc, CorePart part, Bool esp_is_thrptr); extern void VG_(syswrap_init)(void); +extern Bool VG_(setup_client_dataseg)(void); +extern void VG_(track_client_dataseg)(ThreadId tid); #endif #endif // __PUB_CORE_SYSWRAP_H diff --git a/coregrind/pub_core_ume.h b/coregrind/pub_core_ume.h index 856069e92..d9e459c59 100644 --- a/coregrind/pub_core_ume.h +++ b/coregrind/pub_core_ume.h @@ -67,6 +67,7 @@ typedef #if defined(VGO_solaris) Addr init_thrptr; // OUT: architecture-specific user per-thread location Bool real_phdr_present; // OUT: PT_PHDR found, include phdr in auxv + Bool ldsoexec; // OUT: the program is the runtime linker itself #endif Addr entry; // OUT: entrypoint in main executable |