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.
stage2_SOURCES = \
ume.c \
- ${VG_ARCH}/ume_entry.S \
\
vg_scheduler.c \
vg_default.c \
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
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;
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:
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");
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);
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. */
/* 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));
/*====================================================================*/
/* 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++)
| 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)
{
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 ==================== */
// 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");
// 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",
noinst_LIBRARIES = libarch.a
EXTRA_DIST = \
- jmp_with_stack.c \
- ume_entry.S
+ jmp_with_stack.c
BUILT_SOURCES = stage2.lds
CLEANFILES = stage2.lds
+++ /dev/null
-
-/*
- 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
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
#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>
#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 );
-
- return /*True*/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 + x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7];
}
static void test__foreach_map(void)
{
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++) {
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();