diff options
| -rw-r--r-- | ldso/ldso/m68k/elfinterp.c | 326 | ||||
| -rw-r--r-- | ldso/ldso/m68k/resolve.S | 24 | 
2 files changed, 208 insertions, 142 deletions
diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index 80fa1c9ec..204e0e93a 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,223 @@ _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; + +		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; -		switch (reloc_type) -		{ +		_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__) +				    "%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; +		} +	} + +	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); +		}; +	} + +#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 += (unsigned int) tpnt->loadaddr; -		break; +			*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: +			_dl_memcpy ((void *) reloc_addr, +			            (void *) symbol_addr, +			            symtab[symtab_index].st_size); +			break; +  		default: -			_dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname); +			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;  } -int -_dl_parse_relocation_information(struct dyn_elf *arg_rpnt, -	unsigned long rel_addr, unsigned long rel_size) +#if 0 +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 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 */ +	ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) +	ElfW(Addr) old_val; +#endif -	rpnt = (Elf32_Rela *)rel_addr; -	rel_size = rel_size / sizeof (Elf32_Rela); +	(void)scope; +	symtab_index = ELF_R_SYM(rpnt->r_info); +	(void)strtab; -	symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; -	strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; +	reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); +	reloc_type = ELF_R_TYPE(rpnt->r_info); -	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: -				_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]); +	old_val = *reloc_addr;  #endif -				if (symtab_index) -					_dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name); -				_dl_dprintf (2, "\n"); -				_dl_exit (1); -		} + +	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) +{ +	_dl_parse_relocation_information(rpnt, rel_addr, rel_size); +/* +	(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +*/ +} + +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  | 
