diff options
| -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"  | 
