blob: 4d6d5db0705ae3734fa4ad9321da81754a13ee19 [file] [log] [blame]
fitzhardinge7e343cd2003-12-16 02:14:00 +00001#define _FILE_OFFSET_BITS 64
2
3#include <stdio.h>
4#include <elf.h>
5#include <string.h>
6#include <stdlib.h>
7#include <assert.h>
8#include <signal.h>
9#include <fcntl.h>
10#include <errno.h>
11
12#include "vg_include.h"
13
14#include "ume.h"
15#include "ume_arch.h"
16#include "ume_archdefs.h"
17
18static int stack[SIGSTKSZ*4];
19static int our_argc;
20
21/* Where we expect to find all our aux files (namely, stage2) */
22static const char *valgrind_lib = VG_LIBDIR;
23
24/* stage2's name */
25static const char stage2[] = "stage2";
26
27/* Modify the auxv the kernel gave us to make it look like we were
28 execed as the shared object.
29
30 This also inserts a new entry into the auxv table so we can
31 communicate some extra information to stage2 (namely, the fd of the
32 padding file, so it can identiry and remove the padding later).
33*/
34static void *fix_auxv(void *v_init_esp, const struct exeinfo *info)
35{
36 struct ume_auxv *auxv;
37 int *newesp;
38 int seen;
39 int delta;
40 int i;
41 static const int new_entries = 2;
42
43 /* make sure we're running on the private stack */
44 assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);
45
46 /* find the beginning of the AUXV table */
47 auxv = find_auxv(v_init_esp);
48
49 /* Work out how we should move things to make space for the new
50 auxv entry. It seems that ld.so wants a 16-byte aligned stack on
51 entry, so make sure that's the case. */
52 newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
53 delta = (char *)v_init_esp - (char *)newesp;
54
55 memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);
56
57 v_init_esp = (void *)newesp;
58 auxv -= delta/sizeof(*auxv);
59
60 /* stage2 needs this so it can clean up the padding we leave in
61 place when we start it */
62 auxv[0].a_type = AT_UME_PADFD;
63 auxv[0].a_val = as_getpadfd();
64
65 /* This will be needed by valgrind itself so that it can
66 subsequently execve() children. This needs to be done here
67 because /proc/self/exe will go away once we unmap stage1. */
68 auxv[1].a_type = AT_UME_EXECFD;
69 auxv[1].a_val = open("/proc/self/exe", O_RDONLY);
70
71 /* make sure the rest are sane */
72 for(i = new_entries; i < delta/sizeof(*auxv); i++) {
73 auxv[i].a_type = AT_IGNORE;
74 auxv[i].a_val = 0;
75 }
76
77 /* OK, go through and patch up the auxv entries to match the new
78 executable */
79 seen = 0;
80 for(; auxv->a_type != AT_NULL; auxv++) {
81 if (0)
82 printf("doing auxv %p %4x: %d %p\n", auxv, auxv->a_type, auxv->a_val, auxv->a_ptr);
83
84 switch(auxv->a_type) {
85 case AT_PHDR:
86 seen |= 1;
87 auxv->a_val = info->phdr;
88 break;
89
90 case AT_PHNUM:
91 seen |= 2;
92 auxv->a_val = info->phnum;
93 break;
94
95 case AT_BASE:
96 seen |= 4;
97 auxv->a_val = info->interp_base;
98 break;
99
100 case AT_ENTRY:
101 seen |= 8;
102 auxv->a_val = info->entry;
103 break;
104 }
105 }
106
107 /* If we didn't see all the entries we need to fix up, then we
108 can't make the new executable viable. */
109 if (seen != 0xf) {
110 fprintf(stderr, "fix_auxv: we didn't see enough auxv entries (seen=%x)\n", seen);
111 exit(1);
112 }
113
114 return v_init_esp;
115}
116
117static void hoops(void)
118{
119 int err;
120 struct exeinfo info;
121 extern char _end;
122 int *esp;
123 char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
124
125 info.exe_base = PGROUNDUP(&_end);
126 info.exe_end = PGROUNDDN(ume_exec_esp);
127
128 /* XXX FIXME: how can stage1 know where stage2 wants things placed?
129 Options:
130 - we could look for a symbol
131 - it could have a special PHDR (v. ELF specific)
132 - something else?
133 */
134 info.map_base = 0xb0000000;
135 info.setbrk = 1; /* ask do_exec to move the brk-base */
136 info.argv = NULL;
137
138 strcpy(buf, valgrind_lib);
139 strcat(buf, "/");
140 strcat(buf, stage2);
141
142 err = do_exec(buf, &info);
143
144 if (err != 0) {
145 fprintf(stderr, "failed to load %s: %s\n",
146 buf, strerror(err));
147 exit(1);
148 }
149
150 /* Make sure stage2's dynamic linker can't tromp on the lower part
151 of the address space. */
152 as_pad(0, (void *)info.map_base);
153
154 esp = fix_auxv(ume_exec_esp, &info);
155
156 if (0) {
157 int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
158 printf("mapping %10p-%10p %s %02x:%02x %d\n",
159 start, end, perm, maj, min, ino);
160 return 1;
161 }
162 printf("---------- launch stage 2 ----------\n");
163 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
164 foreach_map(prmap);
165 }
166
167 ume_go(info.init_eip, (addr_t)esp);
168}
169
170int main(int argc, char **argv)
171{
172 const char *cp = getenv(VALGRINDLIB);
173
174 if (cp != NULL)
175 valgrind_lib = cp;
176
177 assert(ume_exec_esp != NULL);
178
179 our_argc = argc;
180
181 /* move onto another stack so we can play with the main one */
182 ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
183}