diff options
Diffstat (limited to 'memtestEDK/Memtest/SingleComponents/reloc.c')
-rw-r--r-- | memtestEDK/Memtest/SingleComponents/reloc.c | 268 |
1 files changed, 0 insertions, 268 deletions
diff --git a/memtestEDK/Memtest/SingleComponents/reloc.c b/memtestEDK/Memtest/SingleComponents/reloc.c deleted file mode 100644 index bde268f..0000000 --- a/memtestEDK/Memtest/SingleComponents/reloc.c +++ /dev/null @@ -1,268 +0,0 @@ -/* reloc.c - MemTest-86 Version 3.3 - * - * Released under version 2 of the Gnu Public License. - * By Eric Biederman - */ - -#include "stddef.h" -#include "stdint.h" -#include "elf.h" - -#define __ELF_NATIVE_CLASS 32 -#define ELF_MACHINE_NO_RELA 1 - -/* We use this macro to refer to ELF types independent of the native wordsize. - `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ -#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) -#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) -#define _ElfW_1(e,w,t) e##w##t -#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) - -static inline void __attribute__ ((unused)) -fail_assert(unsigned line_num, unsigned code) { - // Put line num in low bits of %edx and a sentinel in the high bits. - line_num |= 0xEEEC0000; // eek! - asm __volatile__ ("movl %%edx, %%edx" - : "=d"(line_num), "=c" (code) - : "d" (line_num), "c" (code)); - - // Now observe %edx in a virtual machine's debugger. - // Have a nice day. - while(1) {} -} - -// TODO(jcoiner): It would be nice to try to print a message here, -// even though we don't have function calls yet, maybe we can write -// to the screen before going into our infinite loop. -#define assert(expr, code) do { \ - if (!(expr)) { fail_assert(__LINE__, code); } \ - } while(0) - -/* This #define produces dynamic linking inline functions for - bootstrap relocation instead of general-purpose relocation. */ -#define RTLD_BOOTSTRAP - -struct link_map { - ElfW(Addr) l_addr; /* Current load address */ - ElfW(Addr) ll_addr; /* Last load address */ - ElfW(Dyn) *l_ld; - /* Indexed pointers to dynamic section. - [0,DT_NUM) are indexed by the processor-independent tags. - [DT_NUM,DT_NUM+DT_PROCNUM) are indexed by the tag minus DT_LOPROC. - [DT_NUM+DT_PROCNUM, - DT_NUM+DT_PROCNUM+DT_EXTRANUM) - are indexed by DT_EXTRATAGIDX(tagvalue) (see <elf.h>). */ - ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]; -}; - -/* Return the link-time address of _DYNAMIC. Conveniently, this is the - first element of the GOT. This must be inlined in a function which - uses global data. */ -static inline Elf32_Addr __attribute__ ((unused)) -elf_machine_dynamic(void) { - register Elf32_Addr *got asm ("%ebx"); - return *got; -} - -/* Return the run-time load address of the shared object. */ -static inline Elf32_Addr __attribute__ ((unused)) -elf_machine_load_address(void) { - Elf32_Addr addr; - asm volatile ("leal _start@GOTOFF(%%ebx), %0\n" - : "=r" (addr) : : "cc"); - return addr; -} - -/* Perform the relocation specified by RELOC and SYM (which is fully resolved). - MAP is the object containing the reloc. */ -static inline void -elf_machine_rel(struct link_map *map, const Elf32_Rel *reloc, - const Elf32_Sym *sym, Elf32_Addr *const reloc_addr) { - Elf32_Addr ls_addr, s_addr; - Elf32_Addr value; - if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE) - { - *reloc_addr += map->l_addr - map->ll_addr; - return; - } - if (ELF32_R_TYPE(reloc->r_info) == R_386_NONE) { - return; - } - value = sym->st_value; - /* Every section except the undefined section has a base of map->l_addr */ - ls_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->ll_addr; - s_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->l_addr; - - switch (ELF32_R_TYPE (reloc->r_info)) - { - case R_386_COPY: { - /* Roll memcpy by hand as we don't have function calls yet. */ - unsigned char *dest, *src; - long i; - dest = (unsigned char *)reloc_addr; - src = (unsigned char *)(value + s_addr); - for(i = 0; i < sym->st_size; i++) { - dest[i] = src[i]; - } - break; - } - case R_386_GLOB_DAT: - *reloc_addr = s_addr + value; - break; - case R_386_JMP_SLOT: - *reloc_addr = s_addr + value; - break; - case R_386_32: - if (map->ll_addr == 0) { - *reloc_addr += value; - } - *reloc_addr += s_addr - ls_addr; - break; - case R_386_PC32: - if (map->ll_addr == 0) { - *reloc_addr += value - reloc->r_offset; - } - *reloc_addr += (s_addr - map->l_addr) - (ls_addr - map->ll_addr); - break; - default: - assert (! "unexpected dynamic reloc type", 0); - break; - } -} - -/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ - -static inline void __attribute__ ((unused)) -elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr, - ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]) { - if (! dyn) - return; - - while (dyn->d_tag != DT_NULL) { - if (dyn->d_tag < DT_NUM) - info[dyn->d_tag] = dyn; - else if (dyn->d_tag >= DT_LOPROC && - dyn->d_tag < DT_LOPROC + DT_PROCNUM) - info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn; - else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM) - info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM] = dyn; -#if 0 - else { - // JPC this is failing, BOZO! - // Not surprising, there are a bunch of sections we don't - // handle and which modern ELF relocation code in glibc - // will handle and relocate. Bah. - assert (! "bad dynamic tag", dyn->d_tag); - } -#endif - ++dyn; - } - - if (info[DT_PLTGOT] != NULL) - info[DT_PLTGOT]->d_un.d_ptr += l_addr; - if (info[DT_STRTAB] != NULL) - info[DT_STRTAB]->d_un.d_ptr += l_addr; - if (info[DT_SYMTAB] != NULL) - info[DT_SYMTAB]->d_un.d_ptr += l_addr; -#if ! ELF_MACHINE_NO_RELA - if (info[DT_RELA] != NULL) { - assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)), 0); - info[DT_RELA]->d_un.d_ptr += l_addr; - } -#endif -#if ! ELF_MACHINE_NO_REL - if (info[DT_REL] != NULL) { - assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)), 0); - info[DT_REL]->d_un.d_ptr += l_addr; - } -#endif - if (info[DT_PLTREL] != NULL) { -#if ELF_MACHINE_NO_RELA - assert (info[DT_PLTREL]->d_un.d_val == DT_REL, 0); -#elif ELF_MACHINE_NO_REL - assert (info[DT_PLTREL]->d_un.d_val == DT_RELA, 0); -#else - assert (info[DT_PLTREL]->d_un.d_val == DT_REL - || info[DT_PLTREL]->d_un.d_val == DT_RELA, 0); -#endif - } - if (info[DT_JMPREL] != NULL) - info[DT_JMPREL]->d_un.d_ptr += l_addr; -} - -/* Perform the relocations in MAP on the running program image as specified - by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT - relocations; they should be set up to call _dl_runtime_resolve, rather - than fully resolved now. */ - -static inline void -elf_dynamic_do_rel(struct link_map *map, - ElfW(Addr) reladdr, ElfW(Addr) relsize) { - const ElfW(Rel) *r = (const void *) reladdr; - const ElfW(Rel) *end = (const void *) (reladdr + relsize); - - const ElfW(Sym) *const symtab = - (const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr; - - for (; r < end; ++r) { - elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], - (void *) (map->l_addr + r->r_offset)); - } -} - -void _dl_start(void) { - static Elf32_Addr last_load_address = 0; - struct link_map map; - size_t cnt; - - /* Partly clean the `map' structure up. Don't use `memset' - since it might nor be built in or inlined and we cannot make function - calls at this point. */ - for (cnt = 0; cnt < sizeof(map.l_info) / sizeof(map.l_info[0]); ++cnt) { - map.l_info[cnt] = 0; - } - - /* Get the last load address */ - map.ll_addr = last_load_address; - - /* Figure out the run-time load address of the dynamic linker itself. */ - last_load_address = map.l_addr = elf_machine_load_address(); - - /* Read our own dynamic section and fill in the info array. */ - map.l_ld = (void *)map.l_addr + elf_machine_dynamic(); - - elf_get_dynamic_info (map.l_ld, map.l_addr - map.ll_addr, map.l_info); - - /* Relocate ourselves so we can do normal function calls and - * data access using the global offset table. - */ -#if !ELF_MACHINE_NO_REL - elf_dynamic_do_rel(&map, - map.l_info[DT_REL]->d_un.d_ptr, - map.l_info[DT_RELSZ]->d_un.d_val); - if (map.l_info[DT_PLTREL]->d_un.d_val == DT_REL) { - elf_dynamic_do_rel(&map, - map.l_info[DT_JMPREL]->d_un.d_ptr, - map.l_info[DT_PLTRELSZ]->d_un.d_val); - } -#endif - -#if !ELF_MACHINE_NO_RELA - elf_dynamic_do_rela(&map, - map.l_info[DT_RELA]->d_un.d_ptr, - map.l_info[DT_RELASZ]->d_un.d_val); - if (map.l_info[DT_PLTREL]->d_un.d_val == DT_RELA) { - elf_dynamic_do_rela(&map, - map.l_info[DT_JMPREL]->d_un.d_ptr, - map.l_info[DT_PLTRELSZ]->d_un.d_val); - } -#endif - - /* Now life is sane; we can call functions and access global data. - Set up to use the operating system facilities, and find out from - the operating system's program loader where to find the program - header table in core. Put the rest of _dl_start into a separate - function, that way the compiler cannot put accesses to the GOT - before ELF_DYNAMIC_RELOCATE. */ - return; -} |