blob: 247912c7d86d0b0aa57f3d2b7874a3f6e6ac6f73 [file] [log] [blame]
jseward2886b0e2004-01-04 03:46:11 +00001
nethercotebb1c9912004-01-04 16:43:23 +00002/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: preliminaries stage1.c ---*/
nethercotebb1c9912004-01-04 16:43:23 +00004/*--------------------------------------------------------------------*/
5
jseward2886b0e2004-01-04 03:46:11 +00006/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
jseward2886b0e2004-01-04 03:46:11 +00009
10 Copyright (C) 2000-2004 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
fitzhardinge7e343cd2003-12-16 02:14:00 +000031#define _FILE_OFFSET_BITS 64
32
nethercote969ecf12004-10-13 17:29:01 +000033#include <errno.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000034#include <stdio.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000035#include <string.h>
36#include <stdlib.h>
37#include <assert.h>
38#include <signal.h>
39#include <fcntl.h>
nethercote969ecf12004-10-13 17:29:01 +000040#include <sys/mman.h>
fitzhardinge716c2c12004-03-09 00:57:45 +000041#include <sys/resource.h>
nethercote969ecf12004-10-13 17:29:01 +000042#include <unistd.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000043
nethercotef1e5e152004-09-01 23:58:16 +000044#include "core.h"
fitzhardinge7e343cd2003-12-16 02:14:00 +000045#include "ume.h"
sewardjb5f6f512005-03-10 23:59:00 +000046#include "memcheck/memcheck.h"
fitzhardinge7e343cd2003-12-16 02:14:00 +000047
48static int stack[SIGSTKSZ*4];
fitzhardinge7e343cd2003-12-16 02:14:00 +000049
nethercotec25c4492004-10-18 11:52:17 +000050// Initial stack pointer, which points to argc.
51static void* init_sp;
52
fitzhardinge7e343cd2003-12-16 02:14:00 +000053/* Where we expect to find all our aux files (namely, stage2) */
54static const char *valgrind_lib = VG_LIBDIR;
55
56/* stage2's name */
57static const char stage2[] = "stage2";
58
nethercote969ecf12004-10-13 17:29:01 +000059/*------------------------------------------------------------*/
60/*--- Auxv modification ---*/
61/*------------------------------------------------------------*/
62
fitzhardinge7e343cd2003-12-16 02:14:00 +000063/* Modify the auxv the kernel gave us to make it look like we were
64 execed as the shared object.
65
66 This also inserts a new entry into the auxv table so we can
67 communicate some extra information to stage2 (namely, the fd of the
68 padding file, so it can identiry and remove the padding later).
69*/
nethercote31779c72004-07-30 21:50:15 +000070static void *fix_auxv(void *v_init_esp, const struct exeinfo *info,
71 int padfile)
fitzhardinge7e343cd2003-12-16 02:14:00 +000072{
73 struct ume_auxv *auxv;
74 int *newesp;
75 int seen;
76 int delta;
77 int i;
78 static const int new_entries = 2;
79
80 /* make sure we're running on the private stack */
81 assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);
82
83 /* find the beginning of the AUXV table */
84 auxv = find_auxv(v_init_esp);
85
86 /* Work out how we should move things to make space for the new
87 auxv entry. It seems that ld.so wants a 16-byte aligned stack on
88 entry, so make sure that's the case. */
89 newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
90 delta = (char *)v_init_esp - (char *)newesp;
91
92 memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);
93
94 v_init_esp = (void *)newesp;
95 auxv -= delta/sizeof(*auxv);
96
97 /* stage2 needs this so it can clean up the padding we leave in
98 place when we start it */
99 auxv[0].a_type = AT_UME_PADFD;
nethercote31779c72004-07-30 21:50:15 +0000100 auxv[0].u.a_val = padfile;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000101
102 /* This will be needed by valgrind itself so that it can
103 subsequently execve() children. This needs to be done here
104 because /proc/self/exe will go away once we unmap stage1. */
105 auxv[1].a_type = AT_UME_EXECFD;
mueller5ed88f22004-01-06 16:02:29 +0000106 auxv[1].u.a_val = open("/proc/self/exe", O_RDONLY);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000107
108 /* make sure the rest are sane */
109 for(i = new_entries; i < delta/sizeof(*auxv); i++) {
110 auxv[i].a_type = AT_IGNORE;
mueller5ed88f22004-01-06 16:02:29 +0000111 auxv[i].u.a_val = 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000112 }
113
114 /* OK, go through and patch up the auxv entries to match the new
115 executable */
116 seen = 0;
117 for(; auxv->a_type != AT_NULL; auxv++) {
118 if (0)
sewardjb5f6f512005-03-10 23:59:00 +0000119 printf("doing auxv %p %5lld: %lld %p\n",
120 auxv, (Long)auxv->a_type, (Long)auxv->u.a_val, auxv->u.a_ptr);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000121
122 switch(auxv->a_type) {
123 case AT_PHDR:
124 seen |= 1;
mueller5ed88f22004-01-06 16:02:29 +0000125 auxv->u.a_val = info->phdr;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000126 break;
127
128 case AT_PHNUM:
129 seen |= 2;
mueller5ed88f22004-01-06 16:02:29 +0000130 auxv->u.a_val = info->phnum;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000131 break;
132
133 case AT_BASE:
134 seen |= 4;
mueller5ed88f22004-01-06 16:02:29 +0000135 auxv->u.a_val = info->interp_base;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000136 break;
137
138 case AT_ENTRY:
139 seen |= 8;
mueller5ed88f22004-01-06 16:02:29 +0000140 auxv->u.a_val = info->entry;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000141 break;
fitzhardingea1d37c02004-06-14 02:36:09 +0000142
nethercoteeda6b282004-06-15 08:34:10 +0000143#if (defined(AT_SYSINFO) || defined(AT_SYSINFO_EHDR))
144#ifdef AT_SYSINFO
fitzhardingea1d37c02004-06-14 02:36:09 +0000145 case AT_SYSINFO:
nethercoteeda6b282004-06-15 08:34:10 +0000146#endif
nethercote079acf62004-06-14 11:56:59 +0000147#ifdef AT_SYSINFO_EHDR
fitzhardingea1d37c02004-06-14 02:36:09 +0000148 case AT_SYSINFO_EHDR:
nethercote079acf62004-06-14 11:56:59 +0000149#endif
fitzhardingea1d37c02004-06-14 02:36:09 +0000150 auxv->a_type = AT_IGNORE;
151 break;
nethercoteeda6b282004-06-15 08:34:10 +0000152#endif
fitzhardinge7e343cd2003-12-16 02:14:00 +0000153 }
154 }
155
156 /* If we didn't see all the entries we need to fix up, then we
157 can't make the new executable viable. */
158 if (seen != 0xf) {
nethercote2e1cb4c2004-08-05 12:16:13 +0000159 fprintf(stderr, "valgrind: we didn't see enough auxv entries (seen=%x)\n", seen);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000160 exit(1);
161 }
162
163 return v_init_esp;
164}
165
nethercote969ecf12004-10-13 17:29:01 +0000166
167/*------------------------------------------------------------*/
168/*--- Address space padding ---*/
169/*------------------------------------------------------------*/
170
171static void check_mmap(void* res, void* base, int len)
172{
173 if ((void*)-1 == res) {
174 fprintf(stderr, "valgrind: padding mmap(%p, %d) failed during startup.\n"
175 "valgrind: is there a hard virtual memory limit set?\n",
176 base, len);
177 exit(1);
178 }
179}
180
181typedef struct {
182 char* fillgap_start;
183 char* fillgap_end;
184 int fillgap_padfile;
185} fillgap_extra;
186
187static int fillgap(char *segstart, char *segend, const char *perm, off_t off,
188 int maj, int min, int ino, void* e)
189{
190 fillgap_extra* extra = e;
191
192 if (segstart >= extra->fillgap_end)
193 return 0;
194
195 if (segstart > extra->fillgap_start) {
196 void* res = mmap(extra->fillgap_start, segstart - extra->fillgap_start,
197 PROT_NONE, MAP_FIXED|MAP_PRIVATE,
198 extra->fillgap_padfile, 0);
199 check_mmap(res, extra->fillgap_start, segstart - extra->fillgap_start);
200 }
201 extra->fillgap_start = segend;
202
203 return 1;
204}
205
206// Choose a name for the padfile, open it.
207int as_openpadfile(void)
208{
209 char buf[256];
210 int padfile;
211 int seq = 1;
212 do {
213 snprintf(buf, 256, "/tmp/.pad.%d.%d", getpid(), seq++);
214 padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0);
215 unlink(buf);
216 if (padfile == -1 && errno != EEXIST) {
217 fprintf(stderr, "valgrind: couldn't open padfile\n");
218 exit(44);
219 }
220 } while(padfile == -1);
221
222 return padfile;
223}
224
225// Pad all the empty spaces in a range of address space to stop interlopers.
226void as_pad(void *start, void *end, int padfile)
227{
228 fillgap_extra extra;
229 extra.fillgap_start = start;
230 extra.fillgap_end = end;
231 extra.fillgap_padfile = padfile;
232
233 foreach_map(fillgap, &extra);
234
235 if (extra.fillgap_start < extra.fillgap_end) {
236 void* res = mmap(extra.fillgap_start,
237 extra.fillgap_end - extra.fillgap_start,
238 PROT_NONE, MAP_FIXED|MAP_PRIVATE, padfile, 0);
239 check_mmap(res, extra.fillgap_start,
240 extra.fillgap_end - extra.fillgap_start);
241 }
242}
243
244
245/*------------------------------------------------------------*/
246/*--- main() and related pieces ---*/
247/*------------------------------------------------------------*/
248
nethercote31779c72004-07-30 21:50:15 +0000249static int prmap(char *start, char *end, const char *perm, off_t off, int maj,
250 int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +0000251 printf("mapping %10p-%10p %s %02x:%02x %d\n",
252 start, end, perm, maj, min, ino);
253 return 1;
254}
255
nethercote9d072422004-10-13 17:58:36 +0000256static void main2(void)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000257{
nethercote31779c72004-07-30 21:50:15 +0000258 int err, padfile;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000259 struct exeinfo info;
260 extern char _end;
261 int *esp;
262 char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
263
nethercote5462ef72004-10-26 17:03:54 +0000264 info.exe_end = PGROUNDDN(init_sp);
nethercote7f390022004-10-25 17:18:24 +0000265#ifdef HAVE_PIE
266 info.exe_base = ROUNDDN(info.exe_end - 0x02000000, 0x10000000);
267 assert(info.exe_base >= PGROUNDUP(&_end));
268 info.map_base = info.exe_base + 0x01000000;
269#else
nethercote7f390022004-10-25 17:18:24 +0000270 // If this system doesn't have PIE (position-independent executables),
271 // we have to choose a hardwired location for stage2.
fitzhardinge7e343cd2003-12-16 02:14:00 +0000272 info.exe_base = PGROUNDUP(&_end);
nethercote7f390022004-10-25 17:18:24 +0000273 info.map_base = KICKSTART_BASE + 0x01000000;
274#endif
fitzhardinge7e343cd2003-12-16 02:14:00 +0000275
fitzhardinge7e343cd2003-12-16 02:14:00 +0000276 info.argv = NULL;
277
fitzhardingea49f9b52003-12-16 22:26:45 +0000278 snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000279
280 err = do_exec(buf, &info);
281
282 if (err != 0) {
nethercote2e1cb4c2004-08-05 12:16:13 +0000283 fprintf(stderr, "valgrind: failed to load %s: %s\n",
fitzhardinge7e343cd2003-12-16 02:14:00 +0000284 buf, strerror(err));
285 exit(1);
286 }
287
288 /* Make sure stage2's dynamic linker can't tromp on the lower part
289 of the address space. */
nethercote31779c72004-07-30 21:50:15 +0000290 padfile = as_openpadfile();
291 as_pad(0, (void *)info.map_base, padfile);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000292
nethercotec25c4492004-10-18 11:52:17 +0000293 esp = fix_auxv(init_sp, &info, padfile);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000294
295 if (0) {
fitzhardinge7e343cd2003-12-16 02:14:00 +0000296 printf("---------- launch stage 2 ----------\n");
297 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
nethercote31779c72004-07-30 21:50:15 +0000298 foreach_map(prmap, /*dummy*/NULL);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000299 }
300
sewardjb5f6f512005-03-10 23:59:00 +0000301 jmp_with_stack((void (*)(void))info.init_eip, (Addr)esp);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000302}
303
nethercotec25c4492004-10-18 11:52:17 +0000304int main(int argc, char** argv)
fitzhardinge7e343cd2003-12-16 02:14:00 +0000305{
fitzhardinge716c2c12004-03-09 00:57:45 +0000306 struct rlimit rlim;
sewardjb5f6f512005-03-10 23:59:00 +0000307 const char *cp;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000308
nethercotec25c4492004-10-18 11:52:17 +0000309 // Initial stack pointer is to argc, which is immediately before argv[0]
nethercote41c75da2004-10-18 15:34:14 +0000310 // on the stack. Nb: Assumes argc is word-aligned.
nethercotec25c4492004-10-18 11:52:17 +0000311 init_sp = argv - 1;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000312
sewardjb5f6f512005-03-10 23:59:00 +0000313 /* The Linux libc startup sequence leaves this in an apparently
314 undefined state, but it really is defined, so mark it so. */
315 VALGRIND_MAKE_READABLE(init_sp, sizeof(int));
316
317 cp = getenv(VALGRINDLIB);
318
319 if (cp != NULL)
320 valgrind_lib = cp;
321
fitzhardinge716c2c12004-03-09 00:57:45 +0000322 /* Set the address space limit as high as it will go, since we make
323 a lot of very large mappings. */
324 getrlimit(RLIMIT_AS, &rlim);
325 rlim.rlim_cur = rlim.rlim_max;
326 setrlimit(RLIMIT_AS, &rlim);
327
fitzhardinge7e343cd2003-12-16 02:14:00 +0000328 /* move onto another stack so we can play with the main one */
sewardjb5f6f512005-03-10 23:59:00 +0000329 jmp_with_stack(main2, (Addr)stack + sizeof(stack));
fitzhardinge7e343cd2003-12-16 02:14:00 +0000330}
nethercotebb1c9912004-01-04 16:43:23 +0000331
332/*--------------------------------------------------------------------*/
333/*--- end stage1.c ---*/
334/*--------------------------------------------------------------------*/