? b.c ? c.c ? d.c ? diff ? diff.64-bit-alloc ? diff.final2 ? e.c ? f.c ? h.c ? hello ? hello.c ? log ? mcso-norm ? mcso-norm-stripped ? mcso-omit ? mcso-omit-stripped ? n.S ? n.c ? todo ? valgrind-2.1.3.CVS.tar.bz2 ? valgrind-2.1.3.CVS.tar.gz ? vgcore.pid14778 ? vgcore.pid15004 ? vgcore.pid15230 ? vgcore.pid15670 ? vgcore.pid15701 ? vgcore.pid15956 ? x ? xxx ? y ? addrcheck/tests/vg_regtest.tmp.11961 ? cachegrind/tests/vg_regtest.tmp.31814 ? cachegrind/tests/vg_regtest.tmp.31942 ? cachegrind/tests/vg_regtest.tmp.5167 ? corecheck/tests/pth_exit2 ? corecheck/tests/vg_regtest.tmp.16498 ? corecheck/tests/vg_regtest.tmp.21196 ? coregrind/stage2a ? coregrind/stage2b ? coregrind/stage2c ? coregrind/stage2d ? massif/a.out ? massif/g.c ? massif/massif.21330.ps ? massif/massif.21330.txt ? massif/massif.21335.ps ? massif/massif.21335.txt ? massif/massif.21390.ps ? massif/massif.21390.txt ? memcheck/tests/a ? memcheck/tests/a.out ? memcheck/tests/brk2 ? memcheck/tests/vg_regtest.tmp.21102 ? memcheck/tests/vg_regtest.tmp.29644 ? memcheck/tests/x ? none/tests/mq ? none/tests/vg_regtest.tmp.10934 Index: coregrind/Makefile.am =================================================================== RCS file: /home/kde/valgrind/coregrind/Makefile.am,v retrieving revision 1.77 diff -u -3 -p -r1.77 Makefile.am --- coregrind/Makefile.am 25 Aug 2004 16:16:56 -0000 1.77 +++ coregrind/Makefile.am 26 Aug 2004 16:48:07 -0000 @@ -8,7 +8,10 @@ valdir = $(libdir)/valgrind inplacedir = $(top_builddir)/.in_place AM_CPPFLAGS = $(add_includes) -DVG_LIBDIR="\"$(valdir)"\" \ - -DKICKSTART_BASE=$(KICKSTART_BASE) + -DKICKSTART_BASEa=$(KICKSTART_BASEa) \ + -DKICKSTART_BASEb=$(KICKSTART_BASEb) \ + -DKICKSTART_BASEc=$(KICKSTART_BASEc) \ + -DKICKSTART_BASEd=$(KICKSTART_BASEd) AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fno-omit-frame-pointer \ @PREFERRED_STACK_BOUNDARY@ -g -DELFSZ=32 AM_CCASFLAGS = $(add_includes) -I.. @@ -19,7 +22,8 @@ bin_PROGRAMS = \ valgrind val_PROGRAMS = \ - valgrind stage2 \ + valgrind \ + stage2a stage2b stage2c stage2d \ libpthread.so \ vg_inject.so @@ -41,13 +45,14 @@ valgrind_DEPENDENCIES = valgrind_LDFLAGS=-static -g -Wl,-e,_ume_entry valgrind_LDADD= -# Where stage2 will be put. -# Nb: Hard-wiring this sucks. A configure-time test would be better. A -# load-time test would be even better, but would require building stage2 in -# a position-independent way... -KICKSTART_BASE=0xb0000000 +# Where stage2 will be put. Build multiple versions to account for different +# memory layouts. Must be in order from highest to lowest. +KICKSTART_BASEa=0xf0000000 # for 4G user-space +KICKSTART_BASEb=0xb0000000 # for 3G:1G user/kernel (typical) +KICKSTART_BASEc=0x90000000 # for 2.5G:1.5G (unusual) +KICKSTART_BASEd=0x70000000 # for 2G:2G user/kernel (won't work very well) -stage2_SOURCES = \ +st2_sources = \ ume.c \ x86/ume_entry.S \ x86/ume_go.c \ @@ -85,18 +90,37 @@ stage2_SOURCES = \ vg_transtab.c \ vg_ldt.c \ vg_cpuid.S -stage2_DEPENDENCIES = $(srcdir)/valgrind.vs x86/stage2.lds -stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \ - -Wl,-defsym,kickstart_base=$(KICKSTART_BASE) \ +st2_dependencies = $(srcdir)/valgrind.vs x86/stage2.lds +st2_ldflags=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \ -Wl,-T,x86/stage2.lds \ -Wl,-version-script $(srcdir)/valgrind.vs -stage2_LDADD= \ +st2_ldadd= \ demangle/cp-demangle.o \ demangle/cplus-dem.o \ demangle/dyn-string.o \ demangle/safe-ctype.o \ -ldl +stage2a_SOURCES = $(st2_sources) +stage2a_DEPENDENCIES = $(st2_dependencies) +stage2a_LDFLAGS = -Wl,-defsym,kickstart_base=$(KICKSTART_BASEa) $(st2_ldflags) +stage2a_LDADD = $(st2_ldadd) + +stage2b_SOURCES = $(st2_sources) +stage2b_DEPENDENCIES = $(st2_dependencies) +stage2b_LDFLAGS = -Wl,-defsym,kickstart_base=$(KICKSTART_BASEb) $(st2_ldflags) +stage2b_LDADD = $(st2_ldadd) + +stage2c_SOURCES = $(st2_sources) +stage2c_DEPENDENCIES = $(st2_dependencies) +stage2c_LDFLAGS = -Wl,-defsym,kickstart_base=$(KICKSTART_BASEc) $(st2_ldflags) +stage2c_LDADD = $(st2_ldadd) + +stage2d_SOURCES = $(st2_sources) +stage2d_DEPENDENCIES = $(st2_dependencies) +stage2d_LDFLAGS = -Wl,-defsym,kickstart_base=$(KICKSTART_BASEd) $(st2_ldflags) +stage2d_LDADD = $(st2_ldadd) + vg_intercept.c: $(srcdir)/gen_intercepts.pl $(srcdir)/vg_intercept.c.base rm -f $@ $(PERL) $(srcdir)/gen_intercepts.pl < $(srcdir)/vg_intercept.c.base > $@ Index: coregrind/stage1.c =================================================================== RCS file: /home/kde/valgrind/coregrind/stage1.c,v retrieving revision 1.17 diff -u -3 -p -r1.17 stage1.c --- coregrind/stage1.c 25 Aug 2004 16:16:56 -0000 1.17 +++ coregrind/stage1.c 26 Aug 2004 16:48:07 -0000 @@ -51,9 +51,6 @@ static int stack[SIGSTKSZ*4]; /* Where we expect to find all our aux files (namely, stage2) */ static const char *valgrind_lib = VG_LIBDIR; -/* stage2's name */ -static const char stage2[] = "stage2"; - /* Modify the auxv the kernel gave us to make it look like we were execed as the shared object. @@ -169,28 +166,91 @@ static void hoops(void) struct exeinfo info; extern char _end; int *esp; - char buf[strlen(valgrind_lib) + sizeof(stage2) + 16]; + addr_t user_top, best_stage2_base, actual_stage2_base = 0; + int i; + const char* stage2_name = NULL; - info.exe_base = PGROUNDUP(&_end); - info.exe_end = PGROUNDDN(ume_exec_esp); + #define N_STAGE2s 4 + static const char* st2_names[] = + { "stage2a", "stage2b", "stage2c", "stage2d" }; + static const addr_t st2_bases[] = + { KICKSTART_BASEa, KICKSTART_BASEb, KICKSTART_BASEc, KICKSTART_BASEd }; + + // Round up to nearest megabyte. + // + // *** assumes that the stack is at the top of the user address space!! *** + // + user_top = (addr_t)ume_exec_esp | 0xffff; + + #define STAGE2_MINSIZE 0x10000000 + #define STAGE2_MAPBASE_OFFSET 0x01000000 + + // Nb: parens ensure we don't overflow when user_top = 0xffffffff + best_stage2_base = (user_top - STAGE2_MINSIZE) + 1; + if (0) + fprintf(stderr, "best_stage2_base: %p\n", (void*)best_stage2_base); + + // Pick the highest-loading stage2 possible. + for (i = 0; i < N_STAGE2s; i++) { + if (st2_bases[i] <= best_stage2_base) { + // (Possibly) warn if the chosen stage2 doesn't match perfectly. + if (1 && st2_bases[i] != best_stage2_base) { + fprintf(stderr, + "valgrind: WARNING: could not make Valgrind match your address\n" + "valgrind: space layout exactly; %d MB of address space wasted.\n", + (best_stage2_base - st2_bases[i]) / (1024*1024)); + } + stage2_name = st2_names[i]; + actual_stage2_base = st2_bases[i]; + if (0) + fprintf(stderr, "chosen stage2: \"%s\", %p\n", + stage2_name, (void*)actual_stage2_base); + break; + } + } - /* 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.map_base = KICKSTART_BASE + 0x01000000; - info.argv = NULL; + // Abort if none of the stage2s were appropriate. + if (N_STAGE2s == i) { + fprintf(stderr, + "valgrind: Only %p bytes of address space available.\n" + "valgrind: Sorry, that's not enough to run Valgrind.\n" + "valgrind: Are you running a kernel with a small user address space,\n" + "valgrind: or do you have your virtual memory size limited?\n" + "valgrind:\n" + "valgrind: Note that this is not related to how much *physical*\n" + "valgrind: memory your machine has, so buying more RAM won't help!\n" + "valgrind: It's a property of your kernel and/or user environment.\n", + (void*)user_top); + exit(1); + } - snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2); + // Warn if we have a really cramped layout (eg. 2G:2G user/kernel split) + if (user_top < 0xa0000000) { + fprintf(stderr, + "valgrind: WARNING: not much user-level address space available\n" + "valgrind: (only %p bytes).\n" + "valgrind: Valgrind may not work properly, especially under\n" + "valgrind: memory-intensive tools like Memcheck.\n", + (void*)user_top); + } - err = do_exec(buf, &info); + // Setup for loading + info.map_base = actual_stage2_base + STAGE2_MAPBASE_OFFSET; + info.exe_base = PGROUNDUP(&_end); + info.exe_end = PGROUNDDN(ume_exec_esp); + info.argv = NULL; - if (err != 0) { - fprintf(stderr, "valgrind: failed to load %s: %s\n", - buf, strerror(err)); - exit(1); + { + // Load stage2 + char buf[strlen(valgrind_lib) + strlen(stage2_name) + 16]; + snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2_name); + err = do_exec(buf, &info); + + if (err != 0) { + fprintf(stderr, "valgrind: failed to load %s: %s\n", + buf, strerror(err)); + exit(1); + } } /* Make sure stage2's dynamic linker can't tromp on the lower part