diff options
-rw-r--r-- | ldso/ldso/i386/elfinterp.c | 363 |
1 files changed, 193 insertions, 170 deletions
diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index c9eb0b6c5..56f69a9f8 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -2,7 +2,7 @@ /* i386 ELF shared library loader suppport * * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, - * David Engel, Hongjiu Lu and Mitch D'Souza + * David Engel, Hongjiu Lu and Mitch D'Souza * Copyright (C) 2001-2004 Erik Andersen * * All rights reserved. @@ -32,70 +32,71 @@ #include "ldso.h" #if defined (__SUPPORT_LD_DEBUG__) -static const char *_dl_reltypes_tab[] = -{ - [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", - [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", - [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", +static const char *_dl_reltypes_tab[] = { + [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", + [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", + [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", }; static const char * _dl_reltypes(int type) { - static char buf[22]; - const char *str; - - if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) || - NULL == (str = _dl_reltypes_tab[type])) - { - str =_dl_simple_ltoa( buf, (unsigned long)(type)); - } - return str; + static char buf[22]; + const char *str; + + if (type >= (int)(sizeof(_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) || + NULL == (str = _dl_reltypes_tab[type])) { + str = _dl_simple_ltoa(buf, (unsigned long)type); + } + + return str; } -static -void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index) +static void +debug_sym(Elf32_Sym *symtab, char *strtab, int symtab_index) { - if(_dl_debug_symbols) - { - if(symtab_index){ - _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x", - strtab + symtab[symtab_index].st_name, - symtab[symtab_index].st_value, - symtab[symtab_index].st_size, - symtab[symtab_index].st_info, - symtab[symtab_index].st_other, - symtab[symtab_index].st_shndx); - } - } + if (_dl_debug_symbols) { + if (symtab_index) { + _dl_dprintf(_dl_debug_file, + "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x", + strtab + symtab[symtab_index].st_name, + symtab[symtab_index].st_value, + symtab[symtab_index].st_size, + symtab[symtab_index].st_info, + symtab[symtab_index].st_other, + symtab[symtab_index].st_shndx); + } + } } -static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt) +static void +debug_reloc(Elf32_Sym *symtab, char *strtab, ELF_RELOC *rpnt) { - if(_dl_debug_reloc) - { - int symtab_index; - const char *sym; - symtab_index = ELF32_R_SYM(rpnt->r_info); - sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0"; - - if(_dl_debug_symbols) - _dl_dprintf(_dl_debug_file, "\n\t"); - else - _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym); + if (_dl_debug_reloc) { + int symtab_index; + const char *sym; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0"; + + if (_dl_debug_symbols) + _dl_dprintf(_dl_debug_file, "\n\t"); + else + _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym); + #ifdef ELF_USES_RELOCA - _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x", - _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), - rpnt->r_offset, - rpnt->r_addend); + _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x", + _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), + rpnt->r_offset, + rpnt->r_addend); #else - _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n", - _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), - rpnt->r_offset); + _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n", + _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)), + rpnt->r_offset); #endif - } + } } -#endif +#endif /* __SUPPORT_LD_DEBUG__ */ /* Program to load an ELF binary on a linux system, and run it. References to symbols in sharable libraries can be resolved by either @@ -110,7 +111,8 @@ static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt) extern int _dl_linux_resolve(void); -unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) { int reloc_type; ELF_RELOC *this_reloc; @@ -123,42 +125,43 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) unsigned long instr_addr; char *symname; - rel_addr = (char *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr); + rel_addr = (char *)(tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr); 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); - symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr); - strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); - symname= strtab + symtab[symtab_index].st_name; + symtab = (Elf32_Sym *)(intptr_t)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr); + strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); + symname = strtab + symtab[symtab_index].st_name; if (unlikely(reloc_type != R_386_JMP_SLOT)) { _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", - _dl_progname); + _dl_progname); _dl_exit(1); } - /* Address of jump instruction to fix up */ - instr_addr = ((unsigned long) this_reloc->r_offset + - (unsigned long) tpnt->loadaddr); - got_addr = (char **) instr_addr; + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; - /* Get the address of the GOT entry */ + /* Get the address of the GOT entry. */ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _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) - { + 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, - "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); } } if (!_dl_debug_nofixups) { @@ -168,14 +171,14 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) *got_addr = new_addr; #endif - return (unsigned long) new_addr; + 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, Elf32_Sym *symtab, char *strtab)) + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) { unsigned int i; char *strtab; @@ -183,55 +186,57 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt; int symtab_index; - /* Now parse the relocation information */ - rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr); - rel_size = rel_size / sizeof(ELF_RELOC); + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)(rel_addr + tpnt->loadaddr); + rel_size /= sizeof(ELF_RELOC); - symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr); - strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); + symtab = (Elf32_Sym *)(intptr_t)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr); + strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); - for (i = 0; i < rel_size; i++, rpnt++) { - int res; + for (i = 0; i < rel_size; i++, rpnt++) { + int res; symtab_index = ELF32_R_SYM(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) - debug_sym(symtab,strtab,symtab_index); - debug_reloc(symtab,strtab,rpnt); + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); #endif - res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); - if (res==0) continue; + if (res == 0) + continue; - _dl_dprintf(2, "\n%s: ",_dl_progname); + _dl_dprintf(2, "\n%s: ", _dl_progname); if (symtab_index) - _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); - if (unlikely(res <0)) - { - int reloc_type = ELF32_R_TYPE(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); + _dl_dprintf(2, "can't handle reloc type %s\n", + _dl_reltypes(reloc_type)); #else - _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); #endif _dl_exit(-res); - } - if (unlikely(res >0)) - { + } else if (unlikely(res > 0)) { _dl_dprintf(2, "can't resolve symbol\n"); return res; } - } - return 0; -} + } + return 0; +} static int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) { int reloc_type; int symtab_index; @@ -242,21 +247,20 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, unsigned long old_val; #endif - reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { - - symbol_addr = (unsigned long) _dl_find_hash(symname, scope, - elf_machine_type_class(reloc_type)); + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, + 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. + * 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 && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -267,38 +271,42 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, #if defined (__SUPPORT_LD_DEBUG__) old_val = *reloc_addr; #endif - switch (reloc_type) { - case R_386_NONE: - break; - case R_386_32: - *reloc_addr += symbol_addr; - break; - case R_386_PC32: - *reloc_addr += symbol_addr - (unsigned long) reloc_addr; - break; - case R_386_GLOB_DAT: - case R_386_JMP_SLOT: - *reloc_addr = symbol_addr; - break; - case R_386_RELATIVE: - *reloc_addr += (unsigned long) tpnt->loadaddr; - break; - case R_386_COPY: - if (symbol_addr) { + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_32: + *reloc_addr += symbol_addr; + break; + case R_386_PC32: + *reloc_addr += symbol_addr - (unsigned long)reloc_addr; + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_386_RELATIVE: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + case R_386_COPY: + if (symbol_addr) { #if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug_move) - _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", - symname, symtab[symtab_index].st_size, - symbol_addr, reloc_addr); + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); #endif - _dl_memcpy((char *) reloc_addr, (char *) symbol_addr, symtab[symtab_index].st_size); - } - break; - default: - return -1; /*call _dl_exit(1) */ - } + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + #if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug_reloc && _dl_debug_detail) + if (_dl_debug_reloc && _dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); #endif @@ -306,39 +314,43 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, } static int -_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) { int reloc_type; unsigned long *reloc_addr; #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif + (void)scope; (void)symtab; (void)strtab; - reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) old_val = *reloc_addr; #endif - switch (reloc_type) { - case R_386_NONE: - break; - case R_386_JMP_SLOT: - *reloc_addr += (unsigned long) tpnt->loadaddr; - break; - default: - return -1; /*call _dl_exit(1) */ - } + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + #if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug_reloc && _dl_debug_detail) - _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); #endif - return 0; + return 0; } /* This is done as a separate step, because there are cases where @@ -350,8 +362,8 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, /* No, there are cases where the SVr4 linker fails to emit COPY relocs at all */ static int -_dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +_dl_do_copy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) { int reloc_type; int symtab_index; @@ -360,46 +372,57 @@ _dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, int goof = 0; char *symname; - reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); if (reloc_type != R_386_COPY) return 0; + symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; + symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { - symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY); - if (!symbol_addr) goof++; + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY); + if (!symbol_addr) + goof++; } + if (!goof) { #if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug_move) - _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", - symname, symtab[symtab_index].st_size, - symbol_addr, symtab[symtab_index].st_value); + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %x bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, symtab[symtab_index].st_value); #endif - _dl_memcpy((char *) symtab[symtab_index].st_value, - (char *) symbol_addr, symtab[symtab_index].st_size); + + _dl_memcpy((char *)symtab[symtab_index].st_value, + (char *)symbol_addr, symtab[symtab_index].st_size); } return goof; } -void _dl_parse_lazy_relocation_information(struct dyn_elf *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) { (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) +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); } -int _dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size) +int +_dl_parse_copy_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) { return 0; /* just disable for now, remove when we know that it works */ |