blob: d293f8f48098d6d60f538ad6d3098e8469440db2 [file] [log] [blame]
jseward2886b0e2004-01-04 03:46:11 +00001
nethercotebb1c9912004-01-04 16:43:23 +00002/*--------------------------------------------------------------------*/
3/*--- Startup: stage 1 stage1.c ---*/
4/*--------------------------------------------------------------------*/
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;
93 auxv[0].a_val = as_getpadfd();
94
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;
99 auxv[1].a_val = open("/proc/self/exe", O_RDONLY);
100
101 /* make sure the rest are sane */
102 for(i = new_entries; i < delta/sizeof(*auxv); i++) {
103 auxv[i].a_type = AT_IGNORE;
104 auxv[i].a_val = 0;
105 }
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)
112 printf("doing auxv %p %4x: %d %p\n", auxv, auxv->a_type, auxv->a_val, auxv->a_ptr);
113
114 switch(auxv->a_type) {
115 case AT_PHDR:
116 seen |= 1;
117 auxv->a_val = info->phdr;
118 break;
119
120 case AT_PHNUM:
121 seen |= 2;
122 auxv->a_val = info->phnum;
123 break;
124
125 case AT_BASE:
126 seen |= 4;
127 auxv->a_val = info->interp_base;
128 break;
129
130 case AT_ENTRY:
131 seen |= 8;
132 auxv->a_val = info->entry;
133 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;
165 info.setbrk = 1; /* ask do_exec to move the brk-base */
166 info.argv = NULL;
167
fitzhardingea49f9b52003-12-16 22:26:45 +0000168 snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000169
170 err = do_exec(buf, &info);
171
172 if (err != 0) {
173 fprintf(stderr, "failed to load %s: %s\n",
174 buf, strerror(err));
175 exit(1);
176 }
177
178 /* Make sure stage2's dynamic linker can't tromp on the lower part
179 of the address space. */
180 as_pad(0, (void *)info.map_base);
181
182 esp = fix_auxv(ume_exec_esp, &info);
183
184 if (0) {
185 int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
186 printf("mapping %10p-%10p %s %02x:%02x %d\n",
187 start, end, perm, maj, min, ino);
188 return 1;
189 }
190 printf("---------- launch stage 2 ----------\n");
191 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
192 foreach_map(prmap);
193 }
194
195 ume_go(info.init_eip, (addr_t)esp);
196}
197
198int main(int argc, char **argv)
199{
200 const char *cp = getenv(VALGRINDLIB);
201
202 if (cp != NULL)
203 valgrind_lib = cp;
204
205 assert(ume_exec_esp != NULL);
206
207 our_argc = argc;
208
209 /* move onto another stack so we can play with the main one */
210 ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
211}
nethercotebb1c9912004-01-04 16:43:23 +0000212
213/*--------------------------------------------------------------------*/
214/*--- end stage1.c ---*/
215/*--------------------------------------------------------------------*/