summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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
commitef47a5076c8d881d129334b8423f40f7eaa81264 (patch)
tree77ab4ad7f16710ac3d5315a2d71f2e1dc87bb9ec
parent6ce4cb6af9a97426a95c96be844ed599a6f916e1 (diff)
downloaduClibc-alpine-ef47a5076c8d881d129334b8423f40f7eaa81264.tar.bz2
uClibc-alpine-ef47a5076c8d881d129334b8423f40f7eaa81264.tar.xz
Merge from trunk.
-rw-r--r--ldso/ldso/arm/dl-startup.h87
-rw-r--r--ldso/ldso/arm/dl-sysdep.h18
-rw-r--r--ldso/ldso/arm/elfinterp.c1
-rw-r--r--ldso/ldso/cris/dl-startup.h40
-rw-r--r--ldso/ldso/cris/dl-sysdep.h24
-rw-r--r--ldso/ldso/cris/resolve.S88
-rw-r--r--ldso/ldso/i386/dl-startup.h7
-rw-r--r--ldso/ldso/i386/dl-sysdep.h10
-rw-r--r--ldso/ldso/m68k/dl-startup.h56
-rw-r--r--ldso/ldso/m68k/elfinterp.c340
-rw-r--r--ldso/ldso/m68k/resolve.S24
-rw-r--r--ldso/ldso/powerpc/dl-startup.h6
-rw-r--r--ldso/ldso/powerpc/dl-syscalls.h2
-rw-r--r--ldso/ldso/sh/dl-startup.h8
-rw-r--r--ldso/ldso/sh/dl-syscalls.h2
-rw-r--r--ldso/ldso/sh/dl-sysdep.h6
-rw-r--r--ldso/ldso/sh64/dl-startup.h9
-rw-r--r--ldso/ldso/sparc/dl-startup.h72
-rw-r--r--ldso/ldso/sparc/dl-syscalls.h185
-rw-r--r--ldso/ldso/sparc/dl-sysdep.h24
-rw-r--r--ldso/ldso/sparc/elfinterp.c510
-rw-r--r--ldso/ldso/x86_64/dl-startup.h7
-rw-r--r--ldso/ldso/x86_64/dl-syscalls.h2
-rw-r--r--ldso/ldso/x86_64/dl-sysdep.h2
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"