blob: 8b1213037976ea595317080d4735b463af98ad87 [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/*
7 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
9
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
33#include <stdio.h>
34#include <elf.h>
35#include <string.h>
36#include <stdlib.h>
37#include <assert.h>
38#include <signal.h>
39#include <fcntl.h>
40#include <errno.h>
fitzhardinge716c2c12004-03-09 00:57:45 +000041#include <sys/resource.h>
fitzhardinge7e343cd2003-12-16 02:14:00 +000042
43#include "vg_include.h"
44
45#include "ume.h"
46#include "ume_arch.h"
47#include "ume_archdefs.h"
48
49static int stack[SIGSTKSZ*4];
50static int our_argc;
51
52/* Where we expect to find all our aux files (namely, stage2) */
53static const char *valgrind_lib = VG_LIBDIR;
54
55/* stage2's name */
56static const char stage2[] = "stage2";
57
58/* Modify the auxv the kernel gave us to make it look like we were
59 execed as the shared object.
60
61 This also inserts a new entry into the auxv table so we can
62 communicate some extra information to stage2 (namely, the fd of the
63 padding file, so it can identiry and remove the padding later).
64*/
65static void *fix_auxv(void *v_init_esp, const struct exeinfo *info)
66{
67 struct ume_auxv *auxv;
68 int *newesp;
69 int seen;
70 int delta;
71 int i;
72 static const int new_entries = 2;
73
74 /* make sure we're running on the private stack */
75 assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);
76
77 /* find the beginning of the AUXV table */
78 auxv = find_auxv(v_init_esp);
79
80 /* Work out how we should move things to make space for the new
81 auxv entry. It seems that ld.so wants a 16-byte aligned stack on
82 entry, so make sure that's the case. */
83 newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
84 delta = (char *)v_init_esp - (char *)newesp;
85
86 memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);
87
88 v_init_esp = (void *)newesp;
89 auxv -= delta/sizeof(*auxv);
90
91 /* stage2 needs this so it can clean up the padding we leave in
92 place when we start it */
93 auxv[0].a_type = AT_UME_PADFD;
mueller5ed88f22004-01-06 16:02:29 +000094 auxv[0].u.a_val = as_getpadfd();
fitzhardinge7e343cd2003-12-16 02:14:00 +000095
96 /* This will be needed by valgrind itself so that it can
97 subsequently execve() children. This needs to be done here
98 because /proc/self/exe will go away once we unmap stage1. */
99 auxv[1].a_type = AT_UME_EXECFD;
mueller5ed88f22004-01-06 16:02:29 +0000100 auxv[1].u.a_val = open("/proc/self/exe", O_RDONLY);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000101
102 /* make sure the rest are sane */
103 for(i = new_entries; i < delta/sizeof(*auxv); i++) {
104 auxv[i].a_type = AT_IGNORE;
mueller5ed88f22004-01-06 16:02:29 +0000105 auxv[i].u.a_val = 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000106 }
107
108 /* OK, go through and patch up the auxv entries to match the new
109 executable */
110 seen = 0;
111 for(; auxv->a_type != AT_NULL; auxv++) {
112 if (0)
mueller5ed88f22004-01-06 16:02:29 +0000113 printf("doing auxv %p %4x: %d %p\n", auxv, auxv->a_type, auxv->u.a_val, auxv->u.a_ptr);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000114
115 switch(auxv->a_type) {
116 case AT_PHDR:
117 seen |= 1;
mueller5ed88f22004-01-06 16:02:29 +0000118 auxv->u.a_val = info->phdr;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000119 break;
120
121 case AT_PHNUM:
122 seen |= 2;
mueller5ed88f22004-01-06 16:02:29 +0000123 auxv->u.a_val = info->phnum;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000124 break;
125
126 case AT_BASE:
127 seen |= 4;
mueller5ed88f22004-01-06 16:02:29 +0000128 auxv->u.a_val = info->interp_base;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000129 break;
130
131 case AT_ENTRY:
132 seen |= 8;
mueller5ed88f22004-01-06 16:02:29 +0000133 auxv->u.a_val = info->entry;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000134 break;
fitzhardingea1d37c02004-06-14 02:36:09 +0000135
nethercoteeda6b282004-06-15 08:34:10 +0000136#if (defined(AT_SYSINFO) || defined(AT_SYSINFO_EHDR))
137#ifdef AT_SYSINFO
fitzhardingea1d37c02004-06-14 02:36:09 +0000138 case AT_SYSINFO:
nethercoteeda6b282004-06-15 08:34:10 +0000139#endif
nethercote079acf62004-06-14 11:56:59 +0000140#ifdef AT_SYSINFO_EHDR
fitzhardingea1d37c02004-06-14 02:36:09 +0000141 case AT_SYSINFO_EHDR:
nethercote079acf62004-06-14 11:56:59 +0000142#endif
fitzhardingea1d37c02004-06-14 02:36:09 +0000143 auxv->a_type = AT_IGNORE;
144 break;
nethercoteeda6b282004-06-15 08:34:10 +0000145#endif
fitzhardinge7e343cd2003-12-16 02:14:00 +0000146 }
147 }
148
149 /* If we didn't see all the entries we need to fix up, then we
150 can't make the new executable viable. */
151 if (seen != 0xf) {
152 fprintf(stderr, "fix_auxv: we didn't see enough auxv entries (seen=%x)\n", seen);
153 exit(1);
154 }
155
156 return v_init_esp;
157}
158
159static void hoops(void)
160{
161 int err;
162 struct exeinfo info;
163 extern char _end;
164 int *esp;
165 char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
166
167 info.exe_base = PGROUNDUP(&_end);
168 info.exe_end = PGROUNDDN(ume_exec_esp);
169
170 /* XXX FIXME: how can stage1 know where stage2 wants things placed?
171 Options:
172 - we could look for a symbol
173 - it could have a special PHDR (v. ELF specific)
174 - something else?
175 */
176 info.map_base = 0xb0000000;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000177 info.argv = NULL;
178
fitzhardingea49f9b52003-12-16 22:26:45 +0000179 snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000180
181 err = do_exec(buf, &info);
182
183 if (err != 0) {
184 fprintf(stderr, "failed to load %s: %s\n",
185 buf, strerror(err));
186 exit(1);
187 }
188
189 /* Make sure stage2's dynamic linker can't tromp on the lower part
190 of the address space. */
191 as_pad(0, (void *)info.map_base);
192
193 esp = fix_auxv(ume_exec_esp, &info);
194
195 if (0) {
196 int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
197 printf("mapping %10p-%10p %s %02x:%02x %d\n",
198 start, end, perm, maj, min, ino);
199 return 1;
200 }
201 printf("---------- launch stage 2 ----------\n");
202 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
203 foreach_map(prmap);
204 }
205
206 ume_go(info.init_eip, (addr_t)esp);
207}
208
209int main(int argc, char **argv)
210{
fitzhardinge716c2c12004-03-09 00:57:45 +0000211 struct rlimit rlim;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000212 const char *cp = getenv(VALGRINDLIB);
213
214 if (cp != NULL)
215 valgrind_lib = cp;
216
217 assert(ume_exec_esp != NULL);
218
219 our_argc = argc;
220
fitzhardinge716c2c12004-03-09 00:57:45 +0000221 /* Set the address space limit as high as it will go, since we make
222 a lot of very large mappings. */
223 getrlimit(RLIMIT_AS, &rlim);
224 rlim.rlim_cur = rlim.rlim_max;
225 setrlimit(RLIMIT_AS, &rlim);
226
fitzhardinge7e343cd2003-12-16 02:14:00 +0000227 /* move onto another stack so we can play with the main one */
228 ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
229}
nethercotebb1c9912004-01-04 16:43:23 +0000230
231/*--------------------------------------------------------------------*/
232/*--- end stage1.c ---*/
233/*--------------------------------------------------------------------*/