diff options
Diffstat (limited to 'ldso/ldso/arm')
-rw-r--r-- | ldso/ldso/arm/dl-startup.h | 100 | ||||
-rw-r--r-- | ldso/ldso/arm/dl-sysdep.h | 128 |
2 files changed, 119 insertions, 109 deletions
diff --git a/ldso/ldso/arm/dl-startup.h b/ldso/ldso/arm/dl-startup.h index 6e3033959..d4a1ee79b 100644 --- a/ldso/ldso/arm/dl-startup.h +++ b/ldso/ldso/arm/dl-startup.h @@ -1,21 +1,95 @@ -/* Any assmbly language/system dependent hacks needed to setup boot1.c so it - * will work as expected and cope with whatever platform specific wierdness is - * needed for this architecture. */ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org> + */ + /* Overrive the default _dl_boot function, and replace it with a bit of asm. * Then call the real _dl_boot function, which is now named _dl_boot2. */ - -asm("" \ -" .text\n" \ +asm("" \ +" .text\n" \ " .globl _dl_boot\n" \ "_dl_boot:\n" \ -" mov r7, sp\n" \ -" @ldr r0, [sp], #4\n" \ -" mov r0, sp\n" \ +" mov r7, sp\n" \ +" @ldr r0, [sp], #4\n" \ +" mov r0, sp\n" \ " bl _dl_boot2\n" \ -" mov r6, r0\n" \ -" mov r0, r7\n" \ -" mov pc, r6\n" \ +" mov r6, r0\n" \ +" mov r0, r7\n" \ +" mov pc, r6\n" \ ); -#define DL_BOOT(X) static void __attribute__ ((unused)) _dl_boot2 (X) +#define DL_BOOT(X) static __attribute__ ((unused)) void* _dl_boot2 (X) + + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) + +/* Handle relocation of the symbols in the dynamic loader. */ +static inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *reloc_addr += symbol_addr; + break; + case R_ARM_PC24: + { + unsigned long addend; + long newvalue, topbits; + + addend = *reloc_addr & 0x00ffffff; + if (addend & 0x00800000) addend |= 0xff000000; + + newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (topbits != 0xfe000000 && topbits != 0x00000000) + { +#if 0 + // Don't bother with this during ldso initilization... + newvalue = fix_bad_pc24(reloc_addr, symbol_addr) + - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000)) + { + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); + } +#else + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); +#endif + } + newvalue >>= 2; + symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); + *reloc_addr = symbol_addr; + break; + } + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARM_RELATIVE: + *reloc_addr += load_addr; + break; + case R_ARM_COPY: + break; + default: + SEND_STDERR("Unsupported relocation type\n"); + _dl_exit(1); + } +} + + +/* Transfer control to the user's application, once the dynamic loader is + * done. This routine has to exit the current function, then call the + * _dl_elf_main function. */ +#define START() return _dl_elf_main; + + diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h index 96aa62678..ebd258a7f 100644 --- a/ldso/ldso/arm/dl-sysdep.h +++ b/ldso/ldso/arm/dl-sysdep.h @@ -1,123 +1,59 @@ +/* vi: set sw=4 ts=4: */ /* * Various assmbly language/system dependent hacks that are required * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org> */ -/* - * Define this if the system uses RELOCA. - */ +/* Define this if the system uses RELOCA. */ #undef ELF_USES_RELOCA -/* - * Get a pointer to the argv array. On many platforms this can be just - * the address if the first argument, on other platforms we need to - * do something a little more subtle here. - */ -#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) - -/* - * Initialization sequence for a GOT. - */ +/* Initialization sequence for the GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ { \ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ GOT_BASE[1] = (unsigned long) MODULE; \ } -/* - * Here is a macro to perform a relocation. This is only used when - * bootstrapping the dynamic loader. RELP is the relocation that we - * are performing, REL is the pointer to the address we are relocating. - * SYMBOL is the symbol involved in the relocation, and LOAD is the - * load address. - */ -#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ - switch(ELF32_R_TYPE((RELP)->r_info)){ \ - case R_ARM_ABS32: \ - *REL += SYMBOL; \ - break; \ - case R_ARM_PC24: \ - { long newvalue, topbits; \ - unsigned long addend = *REL & 0x00ffffff; \ - if (addend & 0x00800000) addend |= 0xff000000; \ - newvalue=SYMBOL-(unsigned long)REL+(addend<<2); \ - topbits = newvalue & 0xfe000000; \ - if (topbits!=0xfe000000&&topbits!=0x00000000){ \ - newvalue = fix_bad_pc24(REL, SYMBOL) \ - -(unsigned long)REL+(addend<<2); \ - topbits = newvalue & 0xfe000000; \ - if (topbits!=0xfe000000&&topbits!=0x00000000){ \ - SEND_STDERR("R_ARM_PC24 relocation out of range\n");\ - _dl_exit(1); } } \ - newvalue>>=2; \ - SYMBOL=(*REL&0xff000000)|(newvalue & 0x00ffffff); \ - *REL=SYMBOL; \ - } \ - break; \ - case R_ARM_GLOB_DAT: \ - case R_ARM_JUMP_SLOT: \ - *REL = SYMBOL; \ - break; \ - case R_ARM_RELATIVE: \ - *REL += (unsigned long) LOAD; \ - break; \ - case R_ARM_NONE: \ - break; \ - default: \ - SEND_STDERR("Aiieeee!"); \ - _dl_exit(1); \ +static inline unsigned long arm_modulus(unsigned long m, unsigned long p) +{ + unsigned long i,t,inc; + i=p; t=0; + while(!(i&(1<<31))) { + i<<=1; + t++; } - - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. This routine has to exit the current function, then - * call the _dl_elf_main function. - */ - -#define START() return _dl_elf_main; - - + t--; + for(inc=t;inc>2;inc--) { + i=p<<inc; + if(i&(1<<31)) + break; + while(m>=i) { + m-=i; + i<<=1; + if(i&(1<<31)) + break; + if(i<p) + break; + } + } + while(m>=p) { + m-=p; + } + return m; +} +#define do_rem(result, n, base) result=arm_modulus(n,base); /* Here we define the magic numbers that this dynamic loader should accept */ - #define MAGIC1 EM_ARM #undef MAGIC2 + /* Used for error messages */ #define ELF_TARGET "ARM" struct elf_resolve; unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -static inline unsigned long arm_modulus(unsigned long m, unsigned long p) { - unsigned long i,t,inc; - i=p; t=0; - while(!(i&(1<<31))) { - i<<=1; - t++; - } - t--; - for(inc=t;inc>2;inc--) { - i=p<<inc; - if(i&(1<<31)) - break; - while(m>=i) { - m-=i; - i<<=1; - if(i&(1<<31)) - break; - if(i<p) - break; - } - } - while(m>=p) { - m-=p; - } - return m; -} - -#define do_rem(result, n, base) result=arm_modulus(n,base); - /* 4096 bytes alignment */ #define PAGE_ALIGN 0xfffff000 #define ADDR_ALIGN 0xfff |