aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coregrind/m_initimg/initimg-solaris.c38
-rw-r--r--coregrind/m_syswrap/syswrap-solaris.c64
-rw-r--r--coregrind/m_ume/elf.c8
-rw-r--r--coregrind/pub_core_syswrap.h2
-rw-r--r--coregrind/pub_core_ume.h1
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