blob: ad43e336d68d109f92739d78c7ad7043cecbae3c [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>
njnc7561b92005-06-19 01:24:32 +00009#include "../../include/pub_tool_basics.h"
nethercotee65e47b2004-10-14 08:38:06 +000010#include "../../coregrind/ume.h"
11
12#define STKSZ (64*1024)
13
nethercotec25c4492004-10-18 11:52:17 +000014static void* init_sp;
15
nethercote1aec0322004-10-14 08:52:43 +000016//-------------------------------------------------------------------
17// Test foreach_map()
18//-------------------------------------------------------------------
19
nethercotec25c4492004-10-18 11:52:17 +000020static int x[8];
nethercote1aec0322004-10-14 08:52:43 +000021
22static int f(char *start, char *end, const char *perm, off_t off,
23 int maj, int min, int ino, void* dummy) {
24 // Just do some nonsense action with each of the values so that Memcheck
25 // checks that they are valid.
nethercotec25c4492004-10-18 11:52:17 +000026 x[0] = ( start == 0 ? 0 : 1 );
27 x[1] = ( end == 0 ? 0 : 1 );
28 x[2] = ( perm == 0 ? 0 : 1 );
29 x[3] = ( off == 0 ? 0 : 1 );
30 x[4] = ( maj == 0 ? 0 : 1 );
31 x[5] = ( min == 0 ? 0 : 1 );
32 x[6] = ( ino == 0 ? 0 : 1 );
33 x[7] = ( dummy == 0 ? 0 : 1 );
nethercote1aec0322004-10-14 08:52:43 +000034
nethercotec25c4492004-10-18 11:52:17 +000035 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 +000036}
37
38static void test__foreach_map(void)
39{
40 fprintf(stderr, "Calling foreach_map()\n");
41 foreach_map(f, /*dummy*/NULL);
42}
43
44//-------------------------------------------------------------------
nethercote543a63f2004-10-14 09:28:11 +000045// Test find_auxv()
46//-------------------------------------------------------------------
47
48static void test__find_auxv(void)
49{
50 struct ume_auxv *auxv;
51
nethercotec25c4492004-10-18 11:52:17 +000052 assert(init_sp != NULL);
nethercote543a63f2004-10-14 09:28:11 +000053
54 fprintf(stderr, "Calling find_auxv()\n");
nethercoteebf1d862004-11-01 18:22:05 +000055 auxv = find_auxv((UWord*)init_sp);
nethercote543a63f2004-10-14 09:28:11 +000056
57 // Check the auxv value looks sane
nethercotec25c4492004-10-18 11:52:17 +000058 assert((void*)auxv > (void*)init_sp);
59 assert((unsigned int)auxv - (unsigned int)init_sp < 0x10000);
nethercote543a63f2004-10-14 09:28:11 +000060
61 // Scan the auxv, check it looks sane
62 for (; auxv->a_type != AT_NULL; auxv++) {
63 switch(auxv->a_type) {
64 // Check a_type value looks like a plausible small constant
65 case 1 ... 64:
66 break;
67
68 default:
njna4f899c2005-03-24 04:41:16 +000069 fprintf(stderr, "auxv->a_type = %lld\n", (Long)auxv->a_type);
nethercote543a63f2004-10-14 09:28:11 +000070 assert(0);
71 }
72 }
73}
74
75//-------------------------------------------------------------------
nethercote1aec0322004-10-14 08:52:43 +000076// Test do_exec()
77//-------------------------------------------------------------------
78
nethercotee65e47b2004-10-14 08:38:06 +000079static void push_auxv(unsigned char **espp, int type, void *val)
80{
81 struct ume_auxv *auxp = (struct ume_auxv *)*espp;
82 auxp--;
83 auxp->a_type = type;
84 auxp->u.a_ptr = val;
85 *espp = (unsigned char *)auxp;
86}
87
88static void push(unsigned char **espp, void *v)
89{
90 void **vp = *(void ***)espp;
91 *--vp = v;
92 *espp = (unsigned char *)vp;
93}
94
nethercote1aec0322004-10-14 08:52:43 +000095static void test__do_exec(void)
nethercotee65e47b2004-10-14 08:38:06 +000096{
97 struct exeinfo info;
98 int err;
99 unsigned char* newstack;
100 unsigned char *esp;
101
102 info.argv = NULL;
103 info.exe_base = 0x50000000;
104 info.exe_end = 0x50ffffff;
105 info.map_base = 0x51000000;
106
nethercote1aec0322004-10-14 08:52:43 +0000107 fprintf(stderr, "Calling do_exec(\"hello\")\n");
nethercotee65e47b2004-10-14 08:38:06 +0000108 err = do_exec("hello", &info);
109 assert(0 == err);
110
111// printf("info.exe_base=%p exe_end=%p\n",
112// (void*)info.exe_base, (void*)info.exe_end);
113
114 newstack = malloc(STKSZ);
115 assert(0 != newstack);
116
117 esp = newstack+STKSZ;
118
119 /*
120 Set the new executable's stack up like the kernel would after
121 exec.
122
123 These are being pushed onto the stack, towards decreasing
124 addresses.
125 */
126 push_auxv(&esp, AT_NULL, 0); // auxv terminator
127 push_auxv(&esp, AT_ENTRY, (void *)info.entry); // entrypoint of the main executable */
128 push_auxv(&esp, AT_BASE, (void *)info.interp_base); // base address of ld-linux.so
129 push_auxv(&esp, AT_PHDR, (void *)info.phdr); // where the ELF PHDRs are mapped
130 push_auxv(&esp, AT_PHNUM, (void*)info.phnum); // and how many of them
131
132 push(&esp, 0); /* no env */
133 push(&esp, 0); /* no argv */
134 push(&esp, 0); /* argc=0 */
135
136// fprintf(stderr, "ume_go: %p %p\n", (void*)info.init_eip, (void*)esp);
137
sewardj43fe47a2005-03-22 02:43:14 +0000138 jump_and_switch_stacks((Addr)esp, info.init_eip);
nethercotee65e47b2004-10-14 08:38:06 +0000139
nethercote1aec0322004-10-14 08:52:43 +0000140 assert(0); // UNREACHABLE
141}
142
nethercotec25c4492004-10-18 11:52:17 +0000143int main(int argc, char** argv)
nethercote1aec0322004-10-14 08:52:43 +0000144{
nethercotec25c4492004-10-18 11:52:17 +0000145 init_sp = argv - 1;
146
nethercote1aec0322004-10-14 08:52:43 +0000147 test__foreach_map();
nethercote543a63f2004-10-14 09:28:11 +0000148 test__find_auxv();
nethercote1aec0322004-10-14 08:52:43 +0000149 test__do_exec();
150
nethercotee65e47b2004-10-14 08:38:06 +0000151 return 0;
152}