diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-26 04:37:04 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-26 04:37:04 +0000 |
commit | ef47a5076c8d881d129334b8423f40f7eaa81264 (patch) | |
tree | 77ab4ad7f16710ac3d5315a2d71f2e1dc87bb9ec | |
parent | 6ce4cb6af9a97426a95c96be844ed599a6f916e1 (diff) | |
download | uClibc-alpine-ef47a5076c8d881d129334b8423f40f7eaa81264.tar.bz2 uClibc-alpine-ef47a5076c8d881d129334b8423f40f7eaa81264.tar.xz |
Merge from trunk.
-rw-r--r-- | ldso/ldso/arm/dl-startup.h | 87 | ||||
-rw-r--r-- | ldso/ldso/arm/dl-sysdep.h | 18 | ||||
-rw-r--r-- | ldso/ldso/arm/elfinterp.c | 1 | ||||
-rw-r--r-- | ldso/ldso/cris/dl-startup.h | 40 | ||||
-rw-r--r-- | ldso/ldso/cris/dl-sysdep.h | 24 | ||||
-rw-r--r-- | ldso/ldso/cris/resolve.S | 88 | ||||
-rw-r--r-- | ldso/ldso/i386/dl-startup.h | 7 | ||||
-rw-r--r-- | ldso/ldso/i386/dl-sysdep.h | 10 | ||||
-rw-r--r-- | ldso/ldso/m68k/dl-startup.h | 56 | ||||
-rw-r--r-- | ldso/ldso/m68k/elfinterp.c | 340 | ||||
-rw-r--r-- | ldso/ldso/m68k/resolve.S | 24 | ||||
-rw-r--r-- | ldso/ldso/powerpc/dl-startup.h | 6 | ||||
-rw-r--r-- | ldso/ldso/powerpc/dl-syscalls.h | 2 | ||||
-rw-r--r-- | ldso/ldso/sh/dl-startup.h | 8 | ||||
-rw-r--r-- | ldso/ldso/sh/dl-syscalls.h | 2 | ||||
-rw-r--r-- | ldso/ldso/sh/dl-sysdep.h | 6 | ||||
-rw-r--r-- | ldso/ldso/sh64/dl-startup.h | 9 | ||||
-rw-r--r-- | ldso/ldso/sparc/dl-startup.h | 72 | ||||
-rw-r--r-- | ldso/ldso/sparc/dl-syscalls.h | 185 | ||||
-rw-r--r-- | ldso/ldso/sparc/dl-sysdep.h | 24 | ||||
-rw-r--r-- | ldso/ldso/sparc/elfinterp.c | 510 | ||||
-rw-r--r-- | ldso/ldso/x86_64/dl-startup.h | 7 | ||||
-rw-r--r-- | ldso/ldso/x86_64/dl-syscalls.h | 2 | ||||
-rw-r--r-- | ldso/ldso/x86_64/dl-sysdep.h | 2 |
24 files changed, 841 insertions, 689 deletions
diff --git a/ldso/ldso/arm/dl-startup.h b/ldso/ldso/arm/dl-startup.h index b7ab57b0c..43985d002 100644 --- a/ldso/ldso/arm/dl-startup.h +++ b/ldso/ldso/arm/dl-startup.h @@ -1,10 +1,15 @@ /* vi: set sw=4 ts=4: */ /* * Architecture specific code used by dl-startup.c - * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -asm( +#include <features.h> + +#if !defined(__thumb__) +__asm__( " .text\n" " .globl _start\n" " .type _start,%function\n" @@ -40,7 +45,78 @@ asm( " ldr r0, .L_FINI_PROC\n" " ldr r0, [sl, r0]\n" " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#else +__asm__( + " .text\n" + " .arm\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ dumb: can't persuade the linker to make the start address\n" + " @ odd, so use an arm function and change to thumb (_dl_start\n" + " @ is thumb)\n" + " adr r0, __dl_thumb_start+1\n" + " bx r0\n" + "\n\n" + " .thumb\n" + " .globl __dl_thumb_start\n" + " .thumb_func\n" + " .type __dl_thumb_start,%function\n" + "__dl_thumb_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr r7, .L_GET_GOT\n" + ".L_GOT_GOT:\n" + " add r7, pc\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [r7, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " lsl r4, r4, #2\n" + " add sp, r4\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " lsl r3, r1, #2\n" + " add r3, r3, r2\n" + " add r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [r7, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else " mov pc, r6\n" +#endif + "\n\n" ".L_GET_GOT:\n" " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" ".L_SKIP_ARGS:\n" @@ -51,6 +127,7 @@ asm( " .size _start,.-_start\n" ".previous\n" ); +#endif /* Get a pointer to the argv array. On many platforms this can be just @@ -115,9 +192,3 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, _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 794c86a0c..194fd2eb7 100644 --- a/ldso/ldso/arm/dl-sysdep.h +++ b/ldso/ldso/arm/dl-sysdep.h @@ -85,7 +85,25 @@ elf_machine_load_address (void) extern void __dl_start asm ("_dl_start"); Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; Elf32_Addr pcrel_addr; +#if !defined __thumb__ asm ("adr %0, _dl_start" : "=r" (pcrel_addr)); +#else + int tmp; + /* The above adr will not work on thumb because it + * is negative. The only safe way is to temporarily + * swap to arm. + */ + asm( ".align 2\n" + " bx pc\n" + " nop \n" + " .arm \n" + " adr %0, _dl_start\n" + " .align 2\n" + " orr %1, pc, #1\n" + " bx %1\n" + " .force_thumb\n" + : "=r" (pcrel_addr), "=&r" (tmp)); +#endif return pcrel_addr - got_addr; } diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index f5fbc816c..16562642b 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -65,7 +65,6 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; symname = strtab + symtab[symtab_index].st_name; - if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) { _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", _dl_progname); diff --git a/ldso/ldso/cris/dl-startup.h b/ldso/ldso/cris/dl-startup.h index 191657a43..417cb5096 100644 --- a/ldso/ldso/cris/dl-startup.h +++ b/ldso/ldso/cris/dl-startup.h @@ -4,22 +4,43 @@ /* This code fixes the stack pointer so that the dynamic linker * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +asm("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + asm("" \ " .text\n" \ " .globl _start\n" \ " .type _start,@function\n" \ "_start:\n" \ -" move.d $sp,$r10\n" \ -" move.d $pc,$r9\n" \ -" add.d _dl_start - ., $r9\n" \ -" jsr $r9\n" \ -" moveq 0,$r8\n" \ -" move $r8,$srp\n" \ -" jump $r10\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ " .size _start,.-_start\n" \ " .previous\n" \ ); +#endif /* __arch_v32 */ /* 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 @@ -58,8 +79,3 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, break; } } - -/* 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/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h index b58f5e0a3..b5fa89035 100644 --- a/ldso/ldso/cris/dl-sysdep.h +++ b/ldso/ldso/cris/dl-sysdep.h @@ -68,8 +68,32 @@ elf_machine_load_address(void) { Elf32_Addr gotaddr_diff; +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif return gotaddr_diff; } diff --git a/ldso/ldso/cris/resolve.S b/ldso/ldso/cris/resolve.S index 9d2f079fe..9ca27b5ef 100644 --- a/ldso/ldso/cris/resolve.S +++ b/ldso/ldso/cris/resolve.S @@ -17,33 +17,73 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + _dl_linux_resolve: - push $r13 - push $r12 - push $r11 - push $r10 - push $r9 - push $r0 - push $srp - move.d [$sp+7*4],$r11 - move $mof,$r10 + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 #ifdef __PIC__ - move.d $pc,$r0 - sub.d .:GOTOFF,$r0 - move.d _dl_linux_resolver:PLTG,$r9 - add.d $r0,$r9 - jsr $r9 + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 #else - jsr _dl_linux_resolver + jsr _dl_linux_resolver #endif - move.d $r10,[$sp+7*4] - pop $srp - pop $r0 - pop $r9 - pop $r10 - pop $r11 - pop $r12 - pop $r13 - jump [$sp+] + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/ldso/ldso/i386/dl-startup.h b/ldso/ldso/i386/dl-startup.h index cfa412621..933c22c1e 100644 --- a/ldso/ldso/i386/dl-startup.h +++ b/ldso/ldso/i386/dl-startup.h @@ -3,7 +3,7 @@ * Architecture specific code used by dl-startup.c * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> */ -asm( +__asm__ ( " .text\n" " .align 16\n" " .globl _start\n" @@ -64,8 +64,3 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, _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/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h index f004bada8..c0a042c26 100644 --- a/ldso/ldso/i386/dl-sysdep.h +++ b/ldso/ldso/i386/dl-sysdep.h @@ -44,16 +44,18 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent /* 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)) +static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused; +static inline Elf32_Addr elf_machine_dynamic (void) { - register Elf32_Addr *got asm ("%ebx"); + register Elf32_Addr *got __asm__ ("%ebx"); return *got; } /* Return the run-time load address of the shared object. */ -static inline Elf32_Addr __attribute__ ((unused)) +static inline Elf32_Addr elf_machine_load_address (void) attribute_unused; +static inline Elf32_Addr elf_machine_load_address (void) { /* It doesn't matter what variable this is, the reference never makes @@ -61,7 +63,7 @@ elf_machine_load_address (void) via the GOT to make sure the compiler initialized %ebx in time. */ extern int _dl_errno; Elf32_Addr addr; - asm ("leal _dl_start@GOTOFF(%%ebx), %0\n" + __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n" "subl _dl_start@GOT(%%ebx), %0" : "=r" (addr) : "m" (_dl_errno) : "cc"); return addr; diff --git a/ldso/ldso/m68k/dl-startup.h b/ldso/ldso/m68k/dl-startup.h index 07857cf38..fca4b6ccb 100644 --- a/ldso/ldso/m68k/dl-startup.h +++ b/ldso/ldso/m68k/dl-startup.h @@ -4,23 +4,48 @@ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> */ -asm( - " .text\n" - " .globl _start\n" - " .type _start,@function\n" - "_start:\n" - " .set _start,_dl_start\n" - " .size _start,.-_start\n" - " .previous\n" -); +asm ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ +_start:\n\ + move.l %sp, -(%sp)\n\ + jbsr _dl_start\n\ + addq.l #4, %sp\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ +.type _dl_start_user,@function\n\ +_dl_start_user:\n\ + # Save the user entry point address in %a4.\n\ + move.l %d0, %a4\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + move.l _dl_skip_args(%pc), %d0\n\ + # Pop the original argument count\n\ + move.l (%sp)+, %d1\n\ + # Subtract _dl_skip_args from it.\n\ + sub.l %d0, %d1\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + lea (%sp, %d0*4), %sp\n\ + # Push back the modified argument count.\n\ + move.l %d1, -(%sp)\n\ + # Pass our finalizer function to the user in %a1.\n\ + lea _dl_fini(%pc), %a1\n\ + # Initialize %fp with the stack pointer.\n\ + move.l %sp, %fp\n\ + # Jump to the user's entry point.\n\ + jmp (%a4)\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous"); /* 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 int *) & ARGS) +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) /* Handle relocation of the symbols in the dynamic loader. */ -static inline +static __always_inline void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) { @@ -59,12 +84,3 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, _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() \ - __asm__ volatile ( \ - "unlk %%a6\n\t" \ - "jmp %0@" \ - : : "a" (_dl_elf_main)); diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index 80fa1c9ec..914dc0ef6 100644 --- a/ldso/ldso/m68k/elfinterp.c +++ b/ldso/ldso/m68k/elfinterp.c @@ -50,20 +50,20 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) int reloc_type; ELF_RELOC *this_reloc; char *strtab; - Elf32_Sym *symtab; + ElfW(Sym) *symtab; int symtab_index; - ELF_RELOC *rel_addr; + char *rel_addr; char *new_addr; char **got_addr; - unsigned int instr_addr; + ElfW(Addr) instr_addr; char *symname; - rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; - this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); - reloc_type = ELF32_R_TYPE(this_reloc->r_info); - symtab_index = ELF32_R_SYM(this_reloc->r_info); + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); - symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; symname = strtab + symtab[symtab_index].st_name; @@ -74,7 +74,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) } /* Address of the jump instruction to fix up. */ - instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); got_addr = (char **)instr_addr; /* Get the address of the GOT entry. */ @@ -90,159 +90,237 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, - "\n\tpatched: %x ==> %x @ %x", + "\tpatched: %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); } } - if (!_dl_debug_nofixups) { - *got_addr = new_addr; - } -#else - *got_addr = new_addr; + if (!_dl_debug_nofixups) #endif + *got_addr = new_addr; - return (unsigned int)new_addr; + return (unsigned int)new_addr; } -void -_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) { - int i; + unsigned int i; char *strtab; - int reloc_type; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; int symtab_index; - Elf32_Sym *symtab; - Elf32_Rela *rpnt; - unsigned int *reloc_addr; - struct elf_resolve *tpnt = arg_rpnt->dyn; - /* Now parse the relocation information. */ - rpnt = (Elf32_Rela *)rel_addr; - rel_size = rel_size / sizeof (Elf32_Rela); + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; for (i = 0; i < rel_size; i++, rpnt++) { - reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); - reloc_type = ELF32_R_TYPE (rpnt->r_info); - symtab_index = ELF32_R_SYM (rpnt->r_info); + int res; - switch (reloc_type) - { - case R_68K_NONE: - break; - case R_68K_JMP_SLOT: - *reloc_addr += (unsigned int) tpnt->loadaddr; - break; - default: - _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname); + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); #endif - if (symtab_index) - _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); - _dl_dprintf (2, "\n"); - _dl_exit (1); + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; } } + + return 0; } -int -_dl_parse_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) { - int i; - char *strtab; int reloc_type; - int goof = 0; - Elf32_Sym *symtab; - Elf32_Rela *rpnt; - unsigned int *reloc_addr; - unsigned int symbol_addr; int symtab_index; - struct elf_resolve *tpnt = arg_rpnt->dyn; - /* Now parse the relocation information */ + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif - rpnt = (Elf32_Rela *)rel_addr; - rel_size = rel_size / sizeof (Elf32_Rela); + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + }; + } - for (i = 0; i < rel_size; i++, rpnt++) { - reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); - reloc_type = ELF32_R_TYPE (rpnt->r_info); - symtab_index = ELF32_R_SYM (rpnt->r_info); - symbol_addr = 0; - if (symtab_index) { - symbol_addr = (unsigned int) - _dl_find_hash (strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, - elf_machine_type_class(reloc_type)); - - /* We want to allow undefined references to weak symbols - - this might have been intentional. We should not be - linking local symbols here, so all bases should be - covered. */ - if (!symbol_addr - && ELF32_ST_BIND (symtab[symtab_index].st_info) != STB_WEAK) - { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit (1); - } - } - switch (reloc_type) - { - case R_68K_NONE: - break; - case R_68K_8: - *(char *) reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_16: - *(short *) reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_32: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_68K_PC8: - *(char *) reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_PC16: - *(short *) reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_PC32: - *reloc_addr = (symbol_addr + rpnt->r_addend - - (unsigned int) reloc_addr); - break; - case R_68K_GLOB_DAT: - case R_68K_JMP_SLOT: - *reloc_addr = symbol_addr; - break; - case R_68K_RELATIVE: - *reloc_addr = ((unsigned int) tpnt->loadaddr - /* Compatibility kludge. */ - + (rpnt->r_addend ? : *reloc_addr)); - break; - case R_68K_COPY: +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + /* handled by elf_machine_relative() + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) tpnt->loadaddr + / * Compatibility kludge. * / + + (rpnt->r_addend ? : *reloc_addr)); + */ + break; + case R_68K_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif _dl_memcpy ((void *) reloc_addr, (void *) symbol_addr, - symtab[symtab_index].st_size); - break; - default: - _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname); + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]); + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); #endif - if (symtab_index) - _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); - _dl_dprintf (2, "\n"); - _dl_exit (1); - } + + return 0; +} + +#undef LAZY_RELOC_WORKS +#ifdef LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_JMP_SLOT: + *reloc_addr += (unsigned int) tpnt->loadaddr; + break; + default: + _dl_exit(1); } - return goof; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } diff --git a/ldso/ldso/m68k/resolve.S b/ldso/ldso/m68k/resolve.S index 9de314dfb..d9a2929d6 100644 --- a/ldso/ldso/m68k/resolve.S +++ b/ldso/ldso/m68k/resolve.S @@ -8,14 +8,16 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function _dl_linux_resolve: - moveml %a0/%a1,%sp@- -#ifdef __PIC__ - bsrl _dl_linux_resolver@PLTPC -#else - jbsr _dl_linux_resolver -#endif - moveml %sp@+,%a0/%a1 - addql #8,%sp - jmp @(%d0) -.LFE2: - .size _dl_linux_resolve,.LFE2-_dl_linux_resolve + # Save %a0 (struct return address) and %a1. + move.l %a0, -(%sp) + move.l %a1, -(%sp) + # Call the real address resolver. + jbsr _dl_linux_resolver + # Restore register %a0 and %a1. + move.l (%sp)+, %a1 + move.l (%sp)+, %a0 + # Pop parameters + addq.l #8, %sp + # Call real function. + jmp (%d0) +.size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/ldso/ldso/powerpc/dl-startup.h b/ldso/ldso/powerpc/dl-startup.h index e6fd814e5..becfa191e 100644 --- a/ldso/ldso/powerpc/dl-startup.h +++ b/ldso/ldso/powerpc/dl-startup.h @@ -80,9 +80,3 @@ asm( _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\ } \ } -/* - * 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/powerpc/dl-syscalls.h b/ldso/ldso/powerpc/dl-syscalls.h index afb1cd630..996bb87c6 100644 --- a/ldso/ldso/powerpc/dl-syscalls.h +++ b/ldso/ldso/powerpc/dl-syscalls.h @@ -4,5 +4,3 @@ extern int _dl_errno; #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} - -#define MMAP_HAS_6_ARGS diff --git a/ldso/ldso/sh/dl-startup.h b/ldso/ldso/sh/dl-startup.h index 60808f2df..63a65940c 100644 --- a/ldso/ldso/sh/dl-startup.h +++ b/ldso/ldso/sh/dl-startup.h @@ -55,11 +55,3 @@ asm( default: \ _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/sh/dl-syscalls.h b/ldso/ldso/sh/dl-syscalls.h index afb1cd630..996bb87c6 100644 --- a/ldso/ldso/sh/dl-syscalls.h +++ b/ldso/ldso/sh/dl-syscalls.h @@ -4,5 +4,3 @@ extern int _dl_errno; #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} - -#define MMAP_HAS_6_ARGS diff --git a/ldso/ldso/sh/dl-sysdep.h b/ldso/ldso/sh/dl-sysdep.h index 1ecb34898..da109782e 100644 --- a/ldso/ldso/sh/dl-sysdep.h +++ b/ldso/ldso/sh/dl-sysdep.h @@ -25,7 +25,7 @@ struct elf_resolve; extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); -static __inline__ unsigned int +static inline unsigned int _dl_urem(unsigned int n, unsigned int base) { int res; @@ -104,7 +104,7 @@ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_dynamic (void) { register Elf32_Addr *got; - asm ("mov r12,%0" :"=r" (got)); + __asm__ ("mov r12,%0" :"=r" (got)); return *got; } @@ -113,7 +113,7 @@ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_load_address (void) { Elf32_Addr addr; - asm ("mov.l 1f,r0\n\ + __asm__ ("mov.l 1f,r0\n\ mov.l 3f,r2\n\ add r12,r2\n\ mov.l @(r0,r12),r0\n\ diff --git a/ldso/ldso/sh64/dl-startup.h b/ldso/ldso/sh64/dl-startup.h index d40344d08..7701afc71 100644 --- a/ldso/ldso/sh64/dl-startup.h +++ b/ldso/ldso/sh64/dl-startup.h @@ -115,12 +115,3 @@ asm("" \ default: \ _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/sparc/dl-startup.h b/ldso/ldso/sparc/dl-startup.h index 73db327bd..7da972269 100644 --- a/ldso/ldso/sparc/dl-startup.h +++ b/ldso/ldso/sparc/dl-startup.h @@ -3,15 +3,46 @@ * needed for this architecture. See arm/boot1_arch.h for an example of what * can be done. */ -asm( - " .text\n" - " .global _start\n" - " .type _start,%function\n" - "_start:\n" - " .set _start,_dl_start\n" - " .size _start,.-_start\n" - " .previous\n" -); + +asm ("\ + .text\n\ + .global _start\n\ + .type _start,%function\n\ + .align 32\n\ +_start:\n\ + /* Allocate space for functions to drop their arguments. */\n\ + sub %sp, 6*4, %sp\n\ + /* Pass pointer to argument block to _dl_start. */\n\ + call _dl_start\n\ + add %sp, 22*4, %o0\n\ + /* FALTHRU */\n\ + .globl _dl_start_user\n\ + .type _dl_start_user, @function\n\ +_dl_start_user:\n\ + /* Load the PIC register. */\n\ +1: call 2f\n\ + sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ +2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ + add %l7, %o7, %l7\n\ + /* Save the user entry point address in %l0 */\n\ + mov %o0, %l0\n\ + /* See if we were run as a command with the executable file name as an\n\ + extra leading argument. If so, adjust the contents of the stack. */\n\ + sethi %hi(_dl_skip_args), %g2\n\ + or %g2, %lo(_dl_skip_args), %g2\n\ + ld [%l7+%g2], %i0\n\ + ld [%i0], %i0\n\ + tst %i0\n\ + /* Pass our finalizer function to the user in %g1. */\n\ + sethi %hi(_dl_fini), %g1\n\ + or %g1, %lo(_dl_fini), %g1\n\ + ld [%l7+%g1], %g1\n\ + /* Jump to the user's entry point and deallocate the extra stack we got. */\n\ + jmp %l0\n\ + add %sp, 6*4, %sp\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); /* * Get a pointer to the argv array. On many platforms this can be just @@ -19,17 +50,15 @@ asm( * do something a little more subtle here. We assume that argc is stored * at the word just below the argvp that we return here. */ -#define GET_ARGV(ARGVP, ARGS) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP)); +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) /* * Here is a macro to perform a relocation. This is only used when * bootstrapping the dynamic loader. */ #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ - switch(ELF32_R_TYPE((RELP)->r_info)) { \ +switch(ELF_R_TYPE((RELP)->r_info)) { \ case R_SPARC_32: \ - *REL = SYMBOL + (RELP)->r_addend; \ - break; \ case R_SPARC_GLOB_DAT: \ *REL = SYMBOL + (RELP)->r_addend; \ break; \ @@ -38,7 +67,6 @@ asm( REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \ break; \ case R_SPARC_NONE: \ - break; \ case R_SPARC_WDISP30: \ break; \ case R_SPARC_RELATIVE: \ @@ -46,18 +74,4 @@ asm( break; \ default: \ _dl_exit(1); \ - } - -/* - * Transfer control to the user's application, once the dynamic loader - * is done. The crt calls atexit with $g1 if not null, so we need to - * ensure that it contains NULL. - */ - -#define START() \ - __asm__ volatile ( \ - "add %%g0,%%g0,%%g1\n\t" \ - "jmpl %0, %%o7\n\t" \ - "restore %%g0,%%g0,%%g0\n\t" \ - : /*"=r" (status) */ : \ - "r" (_dl_elf_main): "g1", "o0", "o1") +} diff --git a/ldso/ldso/sparc/dl-syscalls.h b/ldso/ldso/sparc/dl-syscalls.h index b1fd73eb8..996bb87c6 100644 --- a/ldso/ldso/sparc/dl-syscalls.h +++ b/ldso/ldso/sparc/dl-syscalls.h @@ -1,187 +1,6 @@ -/* - * This file contains the system call macros and syscall - * numbers used by the shared library loader. - * - * NOTE: This should be integrated/moved to - * sysdeps/linux/sparc/bits/syscalls.h at some point ... - */ - -#define MMAP_HAS_6_ARGS - -#define __NR_exit 1 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_getpid 20 -#define __NR_getuid 24 -#define __NR_getgid 47 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_readlink 58 -#define __NR_mmap 71 -#define __NR_munmap 73 -#define __NR_stat 38 -#define __NR_mprotect 74 - /* We can't use the real errno in ldso, since it has not yet * been dynamicly linked in yet. */ +#include "sys/syscall.h" extern int _dl_errno; +#undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} - -/* Here are the macros which define how this platform makes - * system calls. This particular variant does _not_ set - * errno (note how _dl_errno is used in __syscall_return) since - * these will get called before the errno symbol is dynamicly - * linked. */ - -#define __syscall_return(type, res) \ -do { \ - if (res < -255 || res >= 0) \ - return (type) res; \ - __set_errno(-res); \ - res = -1; \ - return (type) res; \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res)\ - : "r" (__g1) \ - : "o0", "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - register long __o4 __asm__ ("o4") = (long)(arg5); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ -{ \ - long __res; \ - register long __g1 __asm__ ("g1") = __NR_##name; \ - register long __o0 __asm__ ("o0") = (long)(arg1); \ - register long __o1 __asm__ ("o1") = (long)(arg2); \ - register long __o2 __asm__ ("o2") = (long)(arg3); \ - register long __o3 __asm__ ("o3") = (long)(arg4); \ - register long __o4 __asm__ ("o4") = (long)(arg5); \ - register long __o5 __asm__ ("o5") = (long)(arg6); \ - __asm__ __volatile__ ( \ - "t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \ - : "cc"); \ - __syscall_return(type, __res); \ -} diff --git a/ldso/ldso/sparc/dl-sysdep.h b/ldso/ldso/sparc/dl-sysdep.h index 198088b3c..12973e1be 100644 --- a/ldso/ldso/sparc/dl-sysdep.h +++ b/ldso/ldso/sparc/dl-sysdep.h @@ -1,9 +1,9 @@ - +/* 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@codepoet.org> */ -#define LINUXBIN /* Define this if the system uses RELOCA. */ #define ELF_USES_RELOCA @@ -31,19 +31,14 @@ #undef MAGIC2 /* Used for error messages */ -#define ELF_TARGET "Sparc" +#define ELF_TARGET "sparc" -#ifndef COMPILE_ASM -extern unsigned int _dl_linux_resolver(unsigned int reloc_entry, - unsigned int * i); -#endif +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); /* * Define this if you want a dynamic loader that works on Solaris. */ -#ifndef __linux__ -#define SOLARIS_COMPATIBLE -#endif #ifndef COMPILE_ASM /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */ @@ -87,13 +82,6 @@ sparc_mod(unsigned long m, unsigned long p) #define do_rem(result, n, base) ((result) = sparc_mod(n, base)) #endif -/* - * dbx wants the binder to have a specific name. Mustn't disappoint it. - */ -#ifdef SOLARIS_COMPATIBLE -#define _dl_linux_resolve _elf_rtbndr -#endif - /* 4096 bytes alignment */ /* ...but 8192 is required for mmap() on sparc64 kernel */ #define PAGE_ALIGN 0xffffe000 @@ -160,7 +148,7 @@ static inline void elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, Elf32_Word relative_count) { - Elf32_Rela * rpnt = (void *)rel_addr; + Elf32_Rela * rpnt = (void *)rel_addr; --rpnt; do { Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index 8b169b575..9b425fcee 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -33,236 +33,340 @@ References to symbols in sharable libraries can be resolved by either an ELF sharable library or a linux style of shared library. */ /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have - I ever taken any courses on internals. This program was developed using - information available through the book "UNIX SYSTEM V RELEASE 4, - Programmers guide: Ansi C and Programming Support Tools", which did - a more than adequate job of explaining everything required to get this - working. */ + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +/* Some SPARC opcodes we need to use for self-modifying code. */ +#define OPCODE_NOP 0x01000000 /* nop */ +#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ +#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ +#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ +#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ extern int _dl_linux_resolve(void); -unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt) +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) { - int reloc_type; - Elf32_Rela * this_reloc; - char * strtab; - Elf32_Sym * symtab; - Elf32_Rela * rel_addr; - struct elf_resolve * tpnt; - int symtab_index; - char * new_addr; - char ** got_addr; - unsigned int instr_addr; - tpnt = (struct elf_resolve *) plt[2]; - - rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL]; - - /* - * Generate the correct relocation index into the .rela.plt section. - */ - reloc_entry = (reloc_entry >> 10) - 0xc; - - this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry); - - reloc_type = ELF32_R_TYPE(this_reloc->r_info); - symtab_index = ELF32_R_SYM(this_reloc->r_info); - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; - -#ifdef __SUPPORT_LD_DEBUG__ - if (_dl_debug_symbols) { - _dl_dprintf(2, "tpnt = %x\n", tpnt); - _dl_dprintf(2, "reloc = %x\n", this_reloc); - _dl_dprintf(2, "symtab = %x\n", symtab); - _dl_dprintf(2, "strtab = %x\n", strtab); - } + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + /* + * Generate the correct relocation index into the .rela.plt section. + */ + reloc_entry = (reloc_entry >> 10) - 0xc; + + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) #endif + { + got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); + got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + } + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; - if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { - _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n", - _dl_progname, reloc_type); - _dl_exit(30); - }; + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); - /* Address of jump instruction to fix up */ - instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr); - got_addr = (char **) instr_addr; + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; -#ifdef __SUPPORT_LD_DEBUG__ - if (_dl_debug_symbols) { - _dl_dprintf(2, "symtab_index %x\n", symtab_index); + for (i = 0; i < rel_size; i++, rpnt++) { + int res; - _dl_dprintf(2, "Resolving symbol %s\n", - strtab + symtab[symtab_index].st_name); - } -#endif + symtab_index = ELF_R_SYM(rpnt->r_info); - /* Get the address of the GOT entry */ - new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); - if(unlikely(!new_addr)) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit(31); - }; + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " #if defined (__SUPPORT_LD_DEBUG__) - if ((unsigned long) got_addr < 0x40000000) - { - if (_dl_debug_bindings) - { - _dl_dprintf(_dl_debug_file, "\nresolve function: %s", - strtab + symtab[symtab_index].st_name); - if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, - "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; } } - if (!_dl_debug_nofixups) { - got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); - got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } } -#else - got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); - got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */ + + switch (reloc_type) { + case R_SPARC_NONE: + break; + +#if 0 /* these dont really seem to be useful */ + case R_SPARC_8: + *(char *) reloc_addr = symbol_addr; + break; + case R_SPARC_16: + *(short *) reloc_addr = symbol_addr; + break; + case R_SPARC_DISP8: + *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; + case R_SPARC_DISP16: + *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; #endif - _dl_dprintf(2, "Address = %x\n",new_addr); - _dl_exit(32); + case R_SPARC_DISP32: + *reloc_addr = symbol_addr - (unsigned int) reloc_addr; + break; + + case R_SPARC_LO10: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); + break; + + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + *reloc_addr = symbol_addr; + break; + + case R_SPARC_JMP_SLOT: +/* +value = symbol_addr; +value += reloc->r_addend; +disp = value - reloc_addr; +reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff); +reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10); + reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff); + reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10); +*/ + reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); + reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); + break; + + case R_SPARC_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + case R_SPARC_WDISP30: + *reloc_addr = (*reloc_addr & 0xc0000000)| + ((symbol_addr - (unsigned int) reloc_addr) >> 2); + break; + + case R_SPARC_HI22: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10); + break; + + case R_SPARC_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + default: + return -1; /* Calls _dl_exit(1). */ + } - return (unsigned int) new_addr; +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; } -void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +#undef __SPARC_LAZY_RELOC_WORKS +#ifdef __SPARC_LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) { - int i; - char * strtab; - int reloc_type; - int symtab_index; - Elf32_Sym * symtab; - Elf32_Rela * rpnt; - unsigned int * reloc_addr; - struct elf_resolve * tpnt = arg_rpnt->dyn; - - /* Now parse the relocation information */ - rpnt = (Elf32_Rela *)rel_addr; - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; - - for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){ - reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - symtab_index = ELF32_R_SYM(rpnt->r_info); - - switch(reloc_type){ - case R_SPARC_NONE: - break; - case R_SPARC_JMP_SLOT: - break; - default: - _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname); + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); + ElfW(Addr) old_val; #endif - if(symtab_index) _dl_dprintf(2, "'%s'\n", - strtab + symtab[symtab_index].st_name); - _dl_exit(33); - }; - }; + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; } +#endif -int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt, - unsigned long rel_addr, unsigned long rel_size) +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) { - int i; - char * strtab; - int reloc_type; - int goof = 0; - Elf32_Sym * symtab; - Elf32_Rela * rpnt; - unsigned int * reloc_addr; - unsigned int symbol_addr; - int symtab_index; - struct elf_resolve * tpnt = arg_rpnt->dyn; - /* Now parse the relocation information */ - - rpnt = (Elf32_Rela *)rel_addr; - - symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; - strtab = ( char *)tpnt->dynamic_info[DT_STRTAB]; - - for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){ - reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - - if(symtab_index) { - - symbol_addr = (unsigned int) - _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); - - if(!symbol_addr && - ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit (1); - }; - }; - switch(reloc_type){ - case R_SPARC_NONE: - break; - case R_SPARC_32: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_SPARC_DISP32: - *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr; - break; - case R_SPARC_GLOB_DAT: - *reloc_addr = symbol_addr + rpnt->r_addend; - break; - case R_SPARC_JMP_SLOT: - reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); - reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); - break; - case R_SPARC_RELATIVE: - *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend; - break; - case R_SPARC_HI22: - if (!symbol_addr) - symbol_addr = tpnt->loadaddr + rpnt->r_addend; - else - symbol_addr += rpnt->r_addend; - *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10); - break; - case R_SPARC_LO10: - if (!symbol_addr) - symbol_addr = tpnt->loadaddr + rpnt->r_addend; - else - symbol_addr += rpnt->r_addend; - *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); - break; - case R_SPARC_WDISP30: - *reloc_addr = (*reloc_addr & 0xc0000000)| - ((symbol_addr - (unsigned int) reloc_addr) >> 2); - break; - case R_SPARC_COPY: - _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size); - break; - default: - _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname); -#if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]); +#ifdef __SPARC_LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); #endif - if (symtab_index) - _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name); - _dl_exit(34); - }; +} - }; - return goof; +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } diff --git a/ldso/ldso/x86_64/dl-startup.h b/ldso/ldso/x86_64/dl-startup.h index 94d7fd41e..c9a0aac7a 100644 --- a/ldso/ldso/x86_64/dl-startup.h +++ b/ldso/ldso/x86_64/dl-startup.h @@ -6,7 +6,7 @@ * * Parts taken from glibc/sysdeps/x86_64/dl-machine.h */ -asm( +__asm__ ( " .text\n" " .align 16\n" " .global _start\n" @@ -63,8 +63,3 @@ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, _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/x86_64/dl-syscalls.h b/ldso/ldso/x86_64/dl-syscalls.h index afb1cd630..996bb87c6 100644 --- a/ldso/ldso/x86_64/dl-syscalls.h +++ b/ldso/ldso/x86_64/dl-syscalls.h @@ -4,5 +4,3 @@ extern int _dl_errno; #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} - -#define MMAP_HAS_6_ARGS diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h index ae12deb0d..9e2aff14f 100644 --- a/ldso/ldso/x86_64/dl-sysdep.h +++ b/ldso/ldso/x86_64/dl-sysdep.h @@ -90,7 +90,7 @@ elf_machine_load_address (void) and compare it with the current value that we can get via an RIP relative addressing mode. */ - asm ("movq 1f(%%rip), %1\n" + __asm__ ("movq 1f(%%rip), %1\n" "0:\tleaq _dl_start(%%rip), %0\n\t" "subq %1, %0\n\t" ".section\t.data\n" |