blob: 6300c1f39a92aff8bb8722f46924e03c3b4389ee [file] [log] [blame]
nethercotee65e47b2004-10-14 08:38:06 +00001#define ELFSZ 32
2
nethercotec25c4492004-10-18 11:52:17 +00003// This file is a unit self-test for ume.c, jmp_with_stack.c
nethercotee65e47b2004-10-14 08:38:06 +00004
5#include <stdlib.h>
6#include <stdio.h>
7#include <assert.h>
8#include <elf.h>
9#include "../../coregrind/ume.h"
10
11#define STKSZ (64*1024)
12
nethercotec25c4492004-10-18 11:52:17 +000013static void* init_sp;
14
nethercote1aec0322004-10-14 08:52:43 +000015//-------------------------------------------------------------------
16// Test foreach_map()
17//-------------------------------------------------------------------
18
nethercotec25c4492004-10-18 11:52:17 +000019static int x[8];
nethercote1aec0322004-10-14 08:52:43 +000020
21static int f(char *start, char *end, const char *perm, off_t off,
22 int maj, int min, int ino, void* dummy) {
23 // Just do some nonsense action with each of the values so that Memcheck
24 // checks that they are valid.
nethercotec25c4492004-10-18 11:52:17 +000025 x[0] = ( start == 0 ? 0 : 1 );
26 x[1] = ( end == 0 ? 0 : 1 );
27 x[2] = ( perm == 0 ? 0 : 1 );
28 x[3] = ( off == 0 ? 0 : 1 );
29 x[4] = ( maj == 0 ? 0 : 1 );
30 x[5] = ( min == 0 ? 0 : 1 );
31 x[6] = ( ino == 0 ? 0 : 1 );
32 x[7] = ( dummy == 0 ? 0 : 1 );
nethercote1aec0322004-10-14 08:52:43 +000033
nethercotec25c4492004-10-18 11:52:17 +000034 return /*True*/1 + x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7];
nethercote1aec0322004-10-14 08:52:43 +000035}
36
37static void test__foreach_map(void)
38{
39 fprintf(stderr, "Calling foreach_map()\n");
40 foreach_map(f, /*dummy*/NULL);
41}
42
43//-------------------------------------------------------------------
nethercote543a63f2004-10-14 09:28:11 +000044// Test find_auxv()
45//-------------------------------------------------------------------
46
47static void test__find_auxv(void)
48{
49 struct ume_auxv *auxv;
50
nethercotec25c4492004-10-18 11:52:17 +000051 assert(init_sp != NULL);
nethercote543a63f2004-10-14 09:28:11 +000052
53 fprintf(stderr, "Calling find_auxv()\n");
nethercoteebf1d862004-11-01 18:22:05 +000054 auxv = find_auxv((UWord*)init_sp);
nethercote543a63f2004-10-14 09:28:11 +000055
56 // Check the auxv value looks sane
nethercotec25c4492004-10-18 11:52:17 +000057 assert((void*)auxv > (void*)init_sp);
58 assert((unsigned int)auxv - (unsigned int)init_sp < 0x10000);
nethercote543a63f2004-10-14 09:28:11 +000059
60 // Scan the auxv, check it looks sane
61 for (; auxv->a_type != AT_NULL; auxv++) {
62 switch(auxv->a_type) {
63 // Check a_type value looks like a plausible small constant
64 case 1 ... 64:
65 break;
66
67 default:
nethercoteebf1d862004-11-01 18:22:05 +000068 fprintf(stderr, "auxv->a_type = %d\n", auxv->a_type);
nethercote543a63f2004-10-14 09:28:11 +000069 assert(0);
70 }
71 }
72}
73
74//-------------------------------------------------------------------
nethercote1aec0322004-10-14 08:52:43 +000075// Test do_exec()
76//-------------------------------------------------------------------
77
nethercotee65e47b2004-10-14 08:38:06 +000078static void push_auxv(unsigned char **espp, int type, void *val)
79{
80 struct ume_auxv *auxp = (struct ume_auxv *)*espp;
81 auxp--;
82 auxp->a_type = type;
83 auxp->u.a_ptr = val;
84 *espp = (unsigned char *)auxp;
85}
86
87static void push(unsigned char **espp, void *v)
88{
89 void **vp = *(void ***)espp;
90 *--vp = v;
91 *espp = (unsigned char *)vp;
92}
93
nethercote1aec0322004-10-14 08:52:43 +000094static void test__do_exec(void)
nethercotee65e47b2004-10-14 08:38:06 +000095{
96 struct exeinfo info;
97 int err;
98 unsigned char* newstack;
99 unsigned char *esp;
100
101 info.argv = NULL;
102 info.exe_base = 0x50000000;
103 info.exe_end = 0x50ffffff;
104 info.map_base = 0x51000000;
105
nethercote1aec0322004-10-14 08:52:43 +0000106 fprintf(stderr, "Calling do_exec(\"hello\")\n");
nethercotee65e47b2004-10-14 08:38:06 +0000107 err = do_exec("hello", &info);
108 assert(0 == err);
109
110// printf("info.exe_base=%p exe_end=%p\n",
111// (void*)info.exe_base, (void*)info.exe_end);
112
113 newstack = malloc(STKSZ);
114 assert(0 != newstack);
115
116 esp = newstack+STKSZ;
117
118 /*
119 Set the new executable's stack up like the kernel would after
120 exec.
121
122 These are being pushed onto the stack, towards decreasing
123 addresses.
124 */
125 push_auxv(&esp, AT_NULL, 0); // auxv terminator
126 push_auxv(&esp, AT_ENTRY, (void *)info.entry); // entrypoint of the main executable */
127 push_auxv(&esp, AT_BASE, (void *)info.interp_base); // base address of ld-linux.so
128 push_auxv(&esp, AT_PHDR, (void *)info.phdr); // where the ELF PHDRs are mapped
129 push_auxv(&esp, AT_PHNUM, (void*)info.phnum); // and how many of them
130
131 push(&esp, 0); /* no env */
132 push(&esp, 0); /* no argv */
133 push(&esp, 0); /* argc=0 */
134
135// fprintf(stderr, "ume_go: %p %p\n", (void*)info.init_eip, (void*)esp);
136
sewardj43fe47a2005-03-22 02:43:14 +0000137 jump_and_switch_stacks((Addr)esp, info.init_eip);
nethercotee65e47b2004-10-14 08:38:06 +0000138
nethercote1aec0322004-10-14 08:52:43 +0000139 assert(0); // UNREACHABLE
140}
141
nethercotec25c4492004-10-18 11:52:17 +0000142int main(int argc, char** argv)
nethercote1aec0322004-10-14 08:52:43 +0000143{
nethercotec25c4492004-10-18 11:52:17 +0000144 init_sp = argv - 1;
145
nethercote1aec0322004-10-14 08:52:43 +0000146 test__foreach_map();
nethercote543a63f2004-10-14 09:28:11 +0000147 test__find_auxv();
nethercote1aec0322004-10-14 08:52:43 +0000148 test__do_exec();
149
nethercotee65e47b2004-10-14 08:38:06 +0000150 return 0;
151}