|
From: Paul M. <pa...@sa...> - 2004-08-31 01:22:06
|
I have Valgrind working on x86 (and on PPC) using a PIE (position
independent executable) for stage2. I'm not suggesting this for the
release, of course.
This patch adds a configure test for PIE support as suggested by Tom
Hughes. With this patch we compile stage2 as a PIE if we can,
otherwise as a normal executable linked at KICKSTART_BASE. It also
makes a library from vg_replace_malloc.o, which means that we can now
specify the CFLAGS for it correctly (i.e., with -fpic).
We currently compile most of the C files that go into the various
shared libraries without -fpic, which means we end up with text
relocations, which is unfortunate. We really should be using -fpic
for them.
Paul.
diff -urN valgrind-cvs/addrcheck/Makefile.am valgrind-x86/addrcheck/Makefile.am
--- valgrind-cvs/addrcheck/Makefile.am 2004-08-24 18:26:20.000000000 +1000
+++ valgrind-x86/addrcheck/Makefile.am 2004-08-31 09:52:53.209339112 +1000
@@ -21,10 +21,10 @@
vgpreload_addrcheck_so_SOURCES =
vgpreload_addrcheck_so_LDADD = \
- $(top_builddir)/coregrind/vg_replace_malloc.o \
+ $(top_builddir)/coregrind/lib_replace_malloc.a \
../memcheck/mac_replace_strmem.o
vgpreload_addrcheck_so_DEPENDENCIES = \
- $(top_builddir)/coregrind/vg_replace_malloc.o \
+ $(top_builddir)/coregrind/lib_replace_malloc.a \
../memcheck/mac_replace_strmem.o
vgpreload_addrcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
diff -urN valgrind-cvs/configure.in valgrind-x86/configure.in
--- valgrind-cvs/configure.in 2004-08-31 07:57:24.806422384 +1000
+++ valgrind-x86/configure.in 2004-08-31 09:54:01.322368448 +1000
@@ -354,6 +354,22 @@
AC_SUBST(PREFERRED_STACK_BOUNDARY)
+# Check for PIE support in the compiler and linker
+AC_CACHE_CHECK([for PIE support], vg_cv_pie,
+ [safe_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -fpie"
+ safe_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -pie"
+ AC_TRY_LINK([int foo;],
+ [],
+ [vg_cv_pie=yes],
+ [vg_cv_pie=no])
+ CFLAGS=$safe_CFLAGS
+ LDFLAGS=$safe_LDFLAGS])
+if test "$vg_cv_pie" = yes; then
+AC_DEFINE([HAVE_PIE], 1, [can create position-independent executables])
+fi
+AM_CONDITIONAL(USE_PIE, test "$vg_cv_pie" = "yes")
# Checks for header files.
diff -urN valgrind-cvs/coregrind/Makefile.am valgrind-x86/coregrind/Makefile.am
--- valgrind-cvs/coregrind/Makefile.am 2004-08-26 08:49:07.000000000 +1000
+++ valgrind-x86/coregrind/Makefile.am 2004-08-31 10:26:30.000000000 +1000
@@ -26,8 +26,7 @@
EXTRA_DIST = \
vg_libpthread.vs valgrind.vs \
gen_toolint.pl toolfuncs.def \
- gen_intercepts.pl vg_replace_malloc.c.base vg_intercept.c.base \
- vg_replace_malloc.c
+ gen_intercepts.pl vg_replace_malloc.c.base vg_intercept.c.base
BUILT_SOURCES = vg_toolint.c vg_toolint.h
CLEANFILES = vg_toolint.c vg_toolint.h vg_replace_malloc.c vg_intercept.c
@@ -85,11 +84,18 @@
vg_transtab.c \
vg_ldt.c \
vg_cpuid.S
-stage2_DEPENDENCIES = $(srcdir)/valgrind.vs x86/stage2.lds
+stage2_DEPENDENCIES = $(srcdir)/valgrind.vs
stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \
- -Wl,-defsym,kickstart_base=$(KICKSTART_BASE) \
- -Wl,-T,x86/stage2.lds \
- -Wl,-version-script $(srcdir)/valgrind.vs
+ -Wl,-version-script $(srcdir)/valgrind.vs
+if USE_PIE
+stage2_CFLAGS = $(AM_CFLAGS) -fpie
+stage2_LDFLAGS += -pie
+else
+stage2_CFLAGS = $(AM_CFLAGS)
+stage2_DEPENDENCIES += x86/stage2.lds
+stage2_LDFLAGS += -Wl,-defsym,kickstart_base=$(KICKSTART_BASE) \
+ -Wl,-T,x86/stage2.lds
+endif
stage2_LDADD= \
demangle/cp-demangle.o \
demangle/cplus-dem.o \
@@ -122,9 +128,10 @@
vg_libpthread.c \
vg_libpthread_unimp.c \
vg_syscall.S
+libpthread_so_CFLAGS= $(AM_CFLAGS) -fpic
libpthread_so_DEPENDENCIES = $(srcdir)/vg_libpthread.vs
libpthread_so_LDFLAGS = -Werror -fno-omit-frame-pointer -UVG_LIBDIR \
- -shared -fpic -ldl \
+ -shared -ldl \
-Wl,-version-script $(srcdir)/vg_libpthread.vs \
-Wl,-z,nodelete \
-Wl,--soname=libpthread.so.0
@@ -132,15 +139,15 @@
vg_inject_so_SOURCES = \
vg_intercept.c
-# Not really true, but we need to build vg_replace_malloc.o somehow
-vg_inject_so_DEPENDENCIES = \
- vg_replace_malloc.o
-
+vg_inject_so_CFLAGS = $(AM_CFLAGS) -fpic
vg_inject_so_LDFLAGS = \
-shared \
-Wl,--soname,vg_inject.so \
-Wl,-z,initfirst
+lib_replace_malloc_a_SOURCES = vg_replace_malloc.c
+lib_replace_malloc_a_CFLAGS = $(AM_CFLAGS) -fpic
+
noinst_HEADERS = \
ume.h \
ume_arch.h \
@@ -152,9 +159,9 @@
vg_toolint.h \
vg_unsafe.h
-MANUAL_DEPS = $(noinst_HEADERS) $(include_HEADERS) $(inplacedir)/libpthread.so.0
+noinst_LIBRARIES = lib_replace_malloc.a
-vg_replace_malloc.o vg_intercept.o vg_libpthread.o: CFLAGS += -fno-omit-frame-pointer -g -fpic
+MANUAL_DEPS = $(noinst_HEADERS) $(include_HEADERS) $(inplacedir)/libpthread.so.0
all-local:
mkdir -p $(inplacedir)
diff -urN valgrind-cvs/coregrind/demangle/Makefile.am valgrind-x86/coregrind/demangle/Makefile.am
--- valgrind-cvs/coregrind/demangle/Makefile.am 2004-07-04 21:41:39.000000000 +1000
+++ valgrind-x86/coregrind/demangle/Makefile.am 2004-08-31 09:58:41.068444992 +1000
@@ -1,7 +1,10 @@
AM_CPPFLAGS = -I$(top_builddir)/coregrind -I$(top_srcdir)/coregrind \
-I$(top_builddir)/include -I$(top_srcdir)/include
-AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -g
+if USE_PIE
+AM_CFLAGS += -fpie
+endif
noinst_HEADERS = \
ansidecl.h \
diff -urN valgrind-cvs/coregrind/stage1.c valgrind-x86/coregrind/stage1.c
--- valgrind-cvs/coregrind/stage1.c 2004-08-26 08:49:07.000000000 +1000
+++ valgrind-x86/coregrind/stage1.c 2004-08-31 10:12:11.000000000 +1000
@@ -171,16 +171,24 @@
int *esp;
char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
- info.exe_base = PGROUNDUP(&_end);
info.exe_end = PGROUNDDN(ume_exec_esp);
+#ifdef HAVE_PIE
+ info.exe_base = ROUNDDN(info.exe_end - 0x02000000, 0x10000000);
+ assert(info.exe_base >= PGROUNDUP(&_end));
+ info.map_base = info.exe_base + 0x01000000;
+
+#else
/* XXX FIXME: how can stage1 know where stage2 wants things placed?
Options:
- we could look for a symbol
- it could have a special PHDR (v. ELF specific)
- something else?
*/
+ info.exe_base = PGROUNDUP(&_end);
info.map_base = KICKSTART_BASE + 0x01000000;
+#endif
+
info.argv = NULL;
snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
diff -urN valgrind-cvs/coregrind/ume.c valgrind-x86/coregrind/ume.c
--- valgrind-cvs/coregrind/ume.c 2004-08-11 09:37:54.000000000 +1000
+++ valgrind-x86/coregrind/ume.c 2004-08-31 10:00:07.639329384 +1000
@@ -416,6 +416,11 @@
ESZ(Word) interp_size = 0;
int i;
void *entry;
+ ESZ(Addr) ebase = 0;
+
+#ifdef HAVE_PIE
+ ebase = info->exe_base;
+#endif
e = readelf(fd, name);
@@ -423,14 +428,14 @@
return ENOEXEC;
info->phnum = e->e.e_phnum;
- info->entry = e->e.e_entry;
+ info->entry = e->e.e_entry + ebase;
for(i = 0; i < e->e.e_phnum; i++) {
ESZ(Phdr) *ph = &e->p[i];
switch(ph->p_type) {
case PT_PHDR:
- info->phdr = ph->p_vaddr;
+ info->phdr = ph->p_vaddr + ebase;
break;
case PT_LOAD:
@@ -489,8 +494,8 @@
if (info->exe_base != info->exe_end) {
if (minaddr >= maxaddr ||
- (minaddr < info->exe_base ||
- maxaddr > info->exe_end)) {
+ (minaddr + ebase < info->exe_base ||
+ maxaddr + ebase > info->exe_end)) {
fprintf(stderr, "Executable range %p-%p is outside the\n"
"acceptable range %p-%p\n",
(void *)minaddr, (void *)maxaddr,
@@ -499,7 +504,7 @@
}
}
- info->brkbase = mapelf(e, 0); /* map the executable */
+ info->brkbase = mapelf(e, ebase); /* map the executable */
if (info->brkbase == 0)
return ENOMEM;
@@ -532,8 +537,8 @@
} else
entry = (void *)e->e.e_entry;
- info->exe_base = minaddr;
- info->exe_end = maxaddr;
+ info->exe_base = minaddr + ebase;
+ info->exe_end = maxaddr + ebase;
info->init_eip = (addr_t)entry;
diff -urN valgrind-cvs/coregrind/vg_main.c valgrind-x86/coregrind/vg_main.c
--- valgrind-cvs/coregrind/vg_main.c 2004-08-31 07:57:55.252454392 +1000
+++ valgrind-x86/coregrind/vg_main.c 2004-08-31 10:02:43.204375744 +1000
@@ -415,6 +415,10 @@
vgexecfd = auxv->u.a_val;
found |= 2;
break;
+ case AT_PHDR:
+ VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
+ break;
+
}
if ( found != (1|2) ) {
@@ -429,6 +433,7 @@
/*====================================================================*/
/*=== Address space determination ===*/
/*====================================================================*/
+extern char _start[];
static void layout_remaining_space(Addr argc_addr, float ratio)
{
@@ -436,7 +441,10 @@
void* vres;
addr_t client_size, shadow_size;
- VG_(valgrind_base) = (addr_t)&kickstart_base;
+ // VG_(valgrind_base) should have been set by scan_auxv, but if not,
+ // this is a workable approximation
+ if (VG_(valgrind_base) == 0)
+ VG_(valgrind_base) = PGROUNDDN(&_start);
// VG_(valgrind_end) has a slightly different meaning to all the other
// VG_(*_end) vars -- ie. it names the last byte, whereas the others
diff -urN valgrind-cvs/helgrind/Makefile.am valgrind-x86/helgrind/Makefile.am
--- valgrind-cvs/helgrind/Makefile.am 2004-08-24 18:26:22.000000000 +1000
+++ valgrind-x86/helgrind/Makefile.am 2004-08-31 10:06:08.313345648 +1000
@@ -14,8 +14,8 @@
vgskin_helgrind_so_LDFLAGS = -shared
vgpreload_helgrind_so_SOURCES =
-vgpreload_helgrind_so_LDADD = $(top_builddir)/coregrind/vg_replace_malloc.o
-vgpreload_helgrind_so_DEPENDENCIES = $(top_builddir)/coregrind/vg_replace_malloc.o
+vgpreload_helgrind_so_LDADD = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_helgrind_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
vgpreload_helgrind_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
hgincludedir = $(includedir)/valgrind
diff -urN valgrind-cvs/massif/Makefile.am valgrind-x86/massif/Makefile.am
--- valgrind-cvs/massif/Makefile.am 2004-08-24 18:26:23.000000000 +1000
+++ valgrind-x86/massif/Makefile.am 2004-08-31 09:51:09.086325736 +1000
@@ -14,8 +14,8 @@
vgskin_massif_so_LDFLAGS = -shared
vgpreload_massif_so_SOURCES =
-vgpreload_massif_so_LDADD = $(top_builddir)/coregrind/vg_replace_malloc.o
-vgpreload_massif_so_DEPENDENCIES = $(top_builddir)/coregrind/vg_replace_malloc.o
+vgpreload_massif_so_LDADD = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_massif_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
vgpreload_massif_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
all-local:
diff -urN valgrind-cvs/memcheck/Makefile.am valgrind-x86/memcheck/Makefile.am
--- valgrind-cvs/memcheck/Makefile.am 2004-08-24 18:26:23.000000000 +1000
+++ valgrind-x86/memcheck/Makefile.am 2004-08-31 09:51:47.824426968 +1000
@@ -15,8 +15,8 @@
vgpreload_memcheck_so_SOURCES = \
mac_replace_strmem.c
-vgpreload_memcheck_so_LDADD = $(top_builddir)/coregrind/vg_replace_malloc.o
-vgpreload_memcheck_so_DEPENDENCIES = $(top_builddir)/coregrind/vg_replace_malloc.o
+vgpreload_memcheck_so_LDADD = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_memcheck_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
vgpreload_memcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
vgskin_memcheck_so_SOURCES = \
|
|
From: Nicholas N. <nj...@ca...> - 2004-08-31 13:25:28
|
On Tue, 31 Aug 2004, Paul Mackerras wrote: > I have Valgrind working on x86 (and on PPC) using a PIE (position > independent executable) for stage2. I'm not suggesting this for the > release, of course. > > This patch adds a configure test for PIE support as suggested by Tom > Hughes. With this patch we compile stage2 as a PIE if we can, > otherwise as a normal executable linked at KICKSTART_BASE. It also > makes a library from vg_replace_malloc.o, which means that we can now > specify the CFLAGS for it correctly (i.e., with -fpic). It tests for -fpie support from the compiler... didn't you say that -fpic is enough for the compiler? Thanks for doing this, I'd like to see PIE usage go in soon. I like the fact that this change means that the .lds script is no longer needed. I'm not so keen on the #ifdefs, though. > We currently compile most of the C files that go into the various > shared libraries without -fpic, which means we end up with text > relocations, which is unfortunate. We really should be using -fpic > for them. What are text relocations, and why are they bad? Thanks. N |
|
From: Jeremy F. <je...@go...> - 2004-08-31 15:04:42
|
On Tue, 2004-08-31 at 14:25 +0100, Nicholas Nethercote wrote: > Thanks for doing this, I'd like to see PIE usage go in soon. I like the > fact that this change means that the .lds script is no longer needed. That's nice. > What are text relocations, and why are they bad? When you compile with -fpic, the compiler adds an extra level of indirection with the relocatable addresses in a separate section. This means that when ld.so does the fixup at load time, it modifies the separate memory, but leaves the normal code (text) pages untouched so they can be shared with other processes. When you don't use -fpic, the relocation changes the actual code in place, which means that pretty much every page gets written, and therefore not shared. This would be a big deal for something which gets shared a lot (eg, libc), but unless you have a system with lots of instances of Valgrind running, it isn't a big deal, though some architectures may have more strict rules about -fpic. J |