nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 1 | #define ELFSZ 32 |
| 2 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 3 | // This file is a unit self-test for ume.c, jmp_with_stack.c |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 4 | |
| 5 | #include <stdlib.h> |
| 6 | #include <stdio.h> |
| 7 | #include <assert.h> |
| 8 | #include <elf.h> |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame^] | 9 | #include "../../include/pub_tool_basics.h" |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 10 | #include "../../coregrind/ume.h" |
| 11 | |
| 12 | #define STKSZ (64*1024) |
| 13 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 14 | static void* init_sp; |
| 15 | |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 16 | //------------------------------------------------------------------- |
| 17 | // Test foreach_map() |
| 18 | //------------------------------------------------------------------- |
| 19 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 20 | static int x[8]; |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 21 | |
| 22 | static 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. |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 26 | 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 ); |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 34 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 35 | return /*True*/1 + x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7]; |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | static void test__foreach_map(void) |
| 39 | { |
| 40 | fprintf(stderr, "Calling foreach_map()\n"); |
| 41 | foreach_map(f, /*dummy*/NULL); |
| 42 | } |
| 43 | |
| 44 | //------------------------------------------------------------------- |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 45 | // Test find_auxv() |
| 46 | //------------------------------------------------------------------- |
| 47 | |
| 48 | static void test__find_auxv(void) |
| 49 | { |
| 50 | struct ume_auxv *auxv; |
| 51 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 52 | assert(init_sp != NULL); |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 53 | |
| 54 | fprintf(stderr, "Calling find_auxv()\n"); |
nethercote | ebf1d86 | 2004-11-01 18:22:05 +0000 | [diff] [blame] | 55 | auxv = find_auxv((UWord*)init_sp); |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 56 | |
| 57 | // Check the auxv value looks sane |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 58 | assert((void*)auxv > (void*)init_sp); |
| 59 | assert((unsigned int)auxv - (unsigned int)init_sp < 0x10000); |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 60 | |
| 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: |
njn | a4f899c | 2005-03-24 04:41:16 +0000 | [diff] [blame] | 69 | fprintf(stderr, "auxv->a_type = %lld\n", (Long)auxv->a_type); |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 70 | assert(0); |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | //------------------------------------------------------------------- |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 76 | // Test do_exec() |
| 77 | //------------------------------------------------------------------- |
| 78 | |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 79 | static 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 | |
| 88 | static void push(unsigned char **espp, void *v) |
| 89 | { |
| 90 | void **vp = *(void ***)espp; |
| 91 | *--vp = v; |
| 92 | *espp = (unsigned char *)vp; |
| 93 | } |
| 94 | |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 95 | static void test__do_exec(void) |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 96 | { |
| 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 | |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 107 | fprintf(stderr, "Calling do_exec(\"hello\")\n"); |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 108 | 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 | |
sewardj | 43fe47a | 2005-03-22 02:43:14 +0000 | [diff] [blame] | 138 | jump_and_switch_stacks((Addr)esp, info.init_eip); |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 139 | |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 140 | assert(0); // UNREACHABLE |
| 141 | } |
| 142 | |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 143 | int main(int argc, char** argv) |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 144 | { |
nethercote | c25c449 | 2004-10-18 11:52:17 +0000 | [diff] [blame] | 145 | init_sp = argv - 1; |
| 146 | |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 147 | test__foreach_map(); |
nethercote | 543a63f | 2004-10-14 09:28:11 +0000 | [diff] [blame] | 148 | test__find_auxv(); |
nethercote | 1aec032 | 2004-10-14 08:52:43 +0000 | [diff] [blame] | 149 | test__do_exec(); |
| 150 | |
nethercote | e65e47b | 2004-10-14 08:38:06 +0000 | [diff] [blame] | 151 | return 0; |
| 152 | } |