blob: b73c32e0d249754c1e37650d54659be95f454205 [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>
41
42#include "vg_include.h"
43
44#include "ume.h"
45#include "ume_arch.h"
46#include "ume_archdefs.h"
47
48static int stack[SIGSTKSZ*4];
49static int our_argc;
50
51/* Where we expect to find all our aux files (namely, stage2) */
52static const char *valgrind_lib = VG_LIBDIR;
53
54/* stage2's name */
55static const char stage2[] = "stage2";
56
57/* Modify the auxv the kernel gave us to make it look like we were
58 execed as the shared object.
59
60 This also inserts a new entry into the auxv table so we can
61 communicate some extra information to stage2 (namely, the fd of the
62 padding file, so it can identiry and remove the padding later).
63*/
64static void *fix_auxv(void *v_init_esp, const struct exeinfo *info)
65{
66 struct ume_auxv *auxv;
67 int *newesp;
68 int seen;
69 int delta;
70 int i;
71 static const int new_entries = 2;
72
73 /* make sure we're running on the private stack */
74 assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);
75
76 /* find the beginning of the AUXV table */
77 auxv = find_auxv(v_init_esp);
78
79 /* Work out how we should move things to make space for the new
80 auxv entry. It seems that ld.so wants a 16-byte aligned stack on
81 entry, so make sure that's the case. */
82 newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
83 delta = (char *)v_init_esp - (char *)newesp;
84
85 memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);
86
87 v_init_esp = (void *)newesp;
88 auxv -= delta/sizeof(*auxv);
89
90 /* stage2 needs this so it can clean up the padding we leave in
91 place when we start it */
92 auxv[0].a_type = AT_UME_PADFD;
mueller5ed88f22004-01-06 16:02:29 +000093 auxv[0].u.a_val = as_getpadfd();
fitzhardinge7e343cd2003-12-16 02:14:00 +000094
95 /* This will be needed by valgrind itself so that it can
96 subsequently execve() children. This needs to be done here
97 because /proc/self/exe will go away once we unmap stage1. */
98 auxv[1].a_type = AT_UME_EXECFD;
mueller5ed88f22004-01-06 16:02:29 +000099 auxv[1].u.a_val = open("/proc/self/exe", O_RDONLY);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000100
101 /* make sure the rest are sane */
102 for(i = new_entries; i < delta/sizeof(*auxv); i++) {
103 auxv[i].a_type = AT_IGNORE;
mueller5ed88f22004-01-06 16:02:29 +0000104 auxv[i].u.a_val = 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000105 }
106
107 /* OK, go through and patch up the auxv entries to match the new
108 executable */
109 seen = 0;
110 for(; auxv->a_type != AT_NULL; auxv++) {
111 if (0)
mueller5ed88f22004-01-06 16:02:29 +0000112 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 +0000113
114 switch(auxv->a_type) {
115 case AT_PHDR:
116 seen |= 1;
mueller5ed88f22004-01-06 16:02:29 +0000117 auxv->u.a_val = info->phdr;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000118 break;
119
120 case AT_PHNUM:
121 seen |= 2;
mueller5ed88f22004-01-06 16:02:29 +0000122 auxv->u.a_val = info->phnum;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000123 break;
124
125 case AT_BASE:
126 seen |= 4;
mueller5ed88f22004-01-06 16:02:29 +0000127 auxv->u.a_val = info->interp_base;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000128 break;
129
130 case AT_ENTRY:
131 seen |= 8;
mueller5ed88f22004-01-06 16:02:29 +0000132 auxv->u.a_val = info->entry;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000133 break;
134 }
135 }
136
137 /* If we didn't see all the entries we need to fix up, then we
138 can't make the new executable viable. */
139 if (seen != 0xf) {
140 fprintf(stderr, "fix_auxv: we didn't see enough auxv entries (seen=%x)\n", seen);
141 exit(1);
142 }
143
144 return v_init_esp;
145}
146
147static void hoops(void)
148{
149 int err;
150 struct exeinfo info;
151 extern char _end;
152 int *esp;
153 char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
154
155 info.exe_base = PGROUNDUP(&_end);
156 info.exe_end = PGROUNDDN(ume_exec_esp);
157
158 /* XXX FIXME: how can stage1 know where stage2 wants things placed?
159 Options:
160 - we could look for a symbol
161 - it could have a special PHDR (v. ELF specific)
162 - something else?
163 */
164 info.map_base = 0xb0000000;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000165 info.argv = NULL;
166
fitzhardingea49f9b52003-12-16 22:26:45 +0000167 snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000168
169 err = do_exec(buf, &info);
170
171 if (err != 0) {
172 fprintf(stderr, "failed to load %s: %s\n",
173 buf, strerror(err));
174 exit(1);
175 }
176
177 /* Make sure stage2's dynamic linker can't tromp on the lower part
178 of the address space. */
179 as_pad(0, (void *)info.map_base);
180
181 esp = fix_auxv(ume_exec_esp, &info);
182
183 if (0) {
184 int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
185 printf("mapping %10p-%10p %s %02x:%02x %d\n",
186 start, end, perm, maj, min, ino);
187 return 1;
188 }
189 printf("---------- launch stage 2 ----------\n");
190 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
191 foreach_map(prmap);
192 }
193
194 ume_go(info.init_eip, (addr_t)esp);
195}
196
197int main(int argc, char **argv)
198{
199 const char *cp = getenv(VALGRINDLIB);
200
201 if (cp != NULL)
202 valgrind_lib = cp;
203
204 assert(ume_exec_esp != NULL);
205
206 our_argc = argc;
207
208 /* move onto another stack so we can play with the main one */
209 ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
210}
nethercotebb1c9912004-01-04 16:43:23 +0000211
212/*--------------------------------------------------------------------*/
213/*--- end stage1.c ---*/
214/*--------------------------------------------------------------------*/