Arch-abstraction: a nice change that removes the need for ume_entry.S. Instead
of using an assembly hack to find the stack pointer at startup, we find it from
argv. It's much simpler, avoids linking games, is platform independent, and
works on PPC.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2782 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index b08cc3f..56c006f 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -30,12 +30,11 @@
valgrind_SOURCES = \
ume.c \
- ${VG_ARCH}/ume_entry.S \
\
stage1.c \
${VG_ARCH}/jmp_with_stack.c
valgrind_DEPENDENCIES =
-valgrind_LDFLAGS=-static -g -Wl,-e,_ume_entry
+valgrind_LDFLAGS=-static -g
valgrind_LDADD=
# Where stage2 will be put.
@@ -46,7 +45,6 @@
stage2_SOURCES = \
ume.c \
- ${VG_ARCH}/ume_entry.S \
\
vg_scheduler.c \
vg_default.c \
@@ -81,7 +79,7 @@
vg_transtab.c \
vg_cpuid.S
stage2_DEPENDENCIES = $(srcdir)/valgrind.vs ${VG_ARCH}/stage2.lds
-stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \
+stage2_LDFLAGS=-Wl,--export-dynamic -g \
-Wl,-defsym,kickstart_base=$(KICKSTART_BASE) \
-Wl,-T,${VG_ARCH}/stage2.lds \
-Wl,-version-script $(srcdir)/valgrind.vs
diff --git a/coregrind/stage1.c b/coregrind/stage1.c
index 5b4e4db..c6ae5bc 100644
--- a/coregrind/stage1.c
+++ b/coregrind/stage1.c
@@ -46,6 +46,9 @@
static int stack[SIGSTKSZ*4];
+// Initial stack pointer, which points to argc.
+static void* init_sp;
+
/* Where we expect to find all our aux files (namely, stage2) */
static const char *valgrind_lib = VG_LIBDIR;
@@ -257,7 +260,7 @@
char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
info.exe_base = PGROUNDUP(&_end);
- info.exe_end = PGROUNDDN(ume_exec_esp);
+ info.exe_end = PGROUNDDN(init_sp);
/* XXX FIXME: how can stage1 know where stage2 wants things placed?
Options:
@@ -283,7 +286,7 @@
padfile = as_openpadfile();
as_pad(0, (void *)info.map_base, padfile);
- esp = fix_auxv(ume_exec_esp, &info, padfile);
+ esp = fix_auxv(init_sp, &info, padfile);
if (0) {
printf("---------- launch stage 2 ----------\n");
@@ -294,7 +297,7 @@
jmp_with_stack(info.init_eip, (addr_t)esp);
}
-int main(void)
+int main(int argc, char** argv)
{
struct rlimit rlim;
const char *cp = getenv(VALGRINDLIB);
@@ -302,7 +305,9 @@
if (cp != NULL)
valgrind_lib = cp;
- assert(ume_exec_esp != NULL);
+ // Initial stack pointer is to argc, which is immediately before argv[0]
+ // on the stack.
+ init_sp = argv - 1;
/* Set the address space limit as high as it will go, since we make
a lot of very large mappings. */
diff --git a/coregrind/ume.h b/coregrind/ume.h
index 474a0a0..a015ff0 100644
--- a/coregrind/ume.h
+++ b/coregrind/ume.h
@@ -55,8 +55,6 @@
/* Integer type the same size as a pointer */
typedef ESZ(Addr) addr_t;
-extern void *ume_exec_esp; /* esp on entry at exec time */
-
// Jump to a new 'ip' with the stack 'sp'.
void jmp_with_stack(addr_t ip, addr_t sp) __attribute__((noreturn));
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 23c437a..cf61287 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -362,9 +362,9 @@
/*====================================================================*/
/* Look for our AUXV table */
-int scan_auxv(void)
+int scan_auxv(void* init_sp)
{
- const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
+ const struct ume_auxv *auxv = find_auxv((int *)init_sp);
int padfile = -1, found = 0;
for (; auxv->a_type != AT_NULL; auxv++)
@@ -908,7 +908,8 @@
| undefined |
: :
*/
-static Addr setup_client_stack(char **orig_argv, char **orig_envp,
+static Addr setup_client_stack(void* init_sp,
+ char **orig_argv, char **orig_envp,
const struct exeinfo *info,
UInt** client_auxv)
{
@@ -928,7 +929,7 @@
addr_t cl_esp; /* client stack base (initial esp) */
/* use our own auxv as a prototype */
- orig_auxv = find_auxv(ume_exec_esp);
+ orig_auxv = find_auxv(init_sp);
/* ==================== compute sizes ==================== */
@@ -2576,7 +2577,10 @@
// Check we were launched by stage1
// p: n/a
//--------------------------------------------------------------
- padfile = scan_auxv();
+ {
+ void* init_sp = argv - 1;
+ padfile = scan_auxv(init_sp);
+ }
if (0) {
printf("========== main() ==========\n");
@@ -2650,7 +2654,11 @@
// p: load_client() [for 'info']
// p: fix_environment() [for 'env']
//--------------------------------------------------------------
- esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
+ {
+ void* init_sp = argv - 1;
+ esp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
+ &client_auxv);
+ }
if (0)
printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
diff --git a/coregrind/x86/Makefile.am b/coregrind/x86/Makefile.am
index d104a04..17801a3 100644
--- a/coregrind/x86/Makefile.am
+++ b/coregrind/x86/Makefile.am
@@ -11,8 +11,7 @@
noinst_LIBRARIES = libarch.a
EXTRA_DIST = \
- jmp_with_stack.c \
- ume_entry.S
+ jmp_with_stack.c
BUILT_SOURCES = stage2.lds
CLEANFILES = stage2.lds
diff --git a/coregrind/x86/ume_entry.S b/coregrind/x86/ume_entry.S
deleted file mode 100644
index 0802baf..0000000
--- a/coregrind/x86/ume_entry.S
+++ /dev/null
@@ -1,41 +0,0 @@
-
-/*
- This file is part of Valgrind, an extensible x86 protected-mode
- emulator for monitoring program execution on x86-Unixes.
-
- Copyright (C) 2000-2004 Julian Seward
- jseward@acm.org
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
- .text
- .globl _ume_entry
-
- /* Record the very initial value of %esp before starting the
- rest of the executable */
-_ume_entry:
- movl %esp, ume_exec_esp
- jmp _start
-
- .data
- .globl ume_exec_esp
-ume_exec_esp: .long 0
-
-/* Let the linker know we don't need an executable stack */
-.section .note.GNU-stack,"",@progbits
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index 1880925..f3e7f94 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -165,9 +165,7 @@
hello_LDFLAGS = -Wl,-defsym,kickstart_base=0x50000000 \
-Wl,-T,../../coregrind/${VG_ARCH}/stage2.lds
vgtest_ume_SOURCES = vgtest_ume.c
-vgtest_ume_LDFLAGS = -Wl,-e,_ume_entry
vgtest_ume_LDADD = ../../coregrind/ume.o \
- ../../coregrind/ume_entry.o \
../../coregrind/jmp_with_stack.o
# must be built with these flags -- bug only occurred with them
diff --git a/memcheck/tests/vgtest_ume.c b/memcheck/tests/vgtest_ume.c
index 458f6f0..84ca391 100644
--- a/memcheck/tests/vgtest_ume.c
+++ b/memcheck/tests/vgtest_ume.c
@@ -1,6 +1,6 @@
#define ELFSZ 32
-// This file is a unit self-test for ume.c, ume_entry.c, jmp_with_stack.c
+// This file is a unit self-test for ume.c, jmp_with_stack.c
#include <stdlib.h>
#include <stdio.h>
@@ -10,26 +10,28 @@
#define STKSZ (64*1024)
+static void* init_sp;
+
//-------------------------------------------------------------------
// Test foreach_map()
//-------------------------------------------------------------------
-static int x;
+static int x[8];
static int f(char *start, char *end, const char *perm, off_t off,
int maj, int min, int ino, void* dummy) {
// Just do some nonsense action with each of the values so that Memcheck
// checks that they are valid.
- x = ( start == 0 ? 0 : 1 );
- x = ( end == 0 ? 0 : 1 );
- x = ( perm == 0 ? 0 : 1 );
- x = ( off == 0 ? 0 : 1 );
- x = ( maj == 0 ? 0 : 1 );
- x = ( min == 0 ? 0 : 1 );
- x = ( ino == 0 ? 0 : 1 );
- x = ( dummy == 0 ? 0 : 1 );
+ x[0] = ( start == 0 ? 0 : 1 );
+ x[1] = ( end == 0 ? 0 : 1 );
+ x[2] = ( perm == 0 ? 0 : 1 );
+ x[3] = ( off == 0 ? 0 : 1 );
+ x[4] = ( maj == 0 ? 0 : 1 );
+ x[5] = ( min == 0 ? 0 : 1 );
+ x[6] = ( ino == 0 ? 0 : 1 );
+ x[7] = ( dummy == 0 ? 0 : 1 );
- return /*True*/1;
+ return /*True*/1 + x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7];
}
static void test__foreach_map(void)
@@ -46,14 +48,14 @@
{
struct ume_auxv *auxv;
- assert(ume_exec_esp != NULL);
+ assert(init_sp != NULL);
fprintf(stderr, "Calling find_auxv()\n");
- auxv = find_auxv((int*)ume_exec_esp);
+ auxv = find_auxv((int*)init_sp);
// Check the auxv value looks sane
- assert((void*)auxv > (void*)ume_exec_esp);
- assert((unsigned int)auxv - (unsigned int)ume_exec_esp < 0x10000);
+ assert((void*)auxv > (void*)init_sp);
+ assert((unsigned int)auxv - (unsigned int)init_sp < 0x10000);
// Scan the auxv, check it looks sane
for (; auxv->a_type != AT_NULL; auxv++) {
@@ -136,8 +138,10 @@
assert(0); // UNREACHABLE
}
-int main(void)
+int main(int argc, char** argv)
{
+ init_sp = argv - 1;
+
test__foreach_map();
test__find_auxv();
test__do_exec();