blob: 638bf892c06fe30f40082741470da4d6afd0f085 [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
fitzhardingea49f9b52003-12-16 22:26:45 +0000138 snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2);
fitzhardinge7e343cd2003-12-16 02:14:00 +0000139
140 err = do_exec(buf, &info);
141
142 if (err != 0) {
143 fprintf(stderr, "failed to load %s: %s\n",
144 buf, strerror(err));
145 exit(1);
146 }
147
148 /* Make sure stage2's dynamic linker can't tromp on the lower part
149 of the address space. */
150 as_pad(0, (void *)info.map_base);
151
152 esp = fix_auxv(ume_exec_esp, &info);
153
154 if (0) {
155 int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
156 printf("mapping %10p-%10p %s %02x:%02x %d\n",
157 start, end, perm, maj, min, ino);
158 return 1;
159 }
160 printf("---------- launch stage 2 ----------\n");
161 printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
162 foreach_map(prmap);
163 }
164
165 ume_go(info.init_eip, (addr_t)esp);
166}
167
168int main(int argc, char **argv)
169{
170 const char *cp = getenv(VALGRINDLIB);
171
172 if (cp != NULL)
173 valgrind_lib = cp;
174
175 assert(ume_exec_esp != NULL);
176
177 our_argc = argc;
178
179 /* move onto another stack so we can play with the main one */
180 ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
181}