diff options
| author | matt <matt@NetBSD.org> | 2001-07-15 01:44:10 +0000 |
|---|---|---|
| committer | matt <matt@NetBSD.org> | 2001-07-15 01:44:10 +0000 |
| commit | 00f7d1ea671d88301ef56f3e78efc357c5b2e34f (patch) | |
| tree | 5ed45a6f02c2aca82b17163db58a87424e46de61 /libexec | |
| parent | 861dbe4370d994e4c25cd9ec19eecdd780030c82 (diff) | |
Add support for ARM ELF dynamic relocs.
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ld.elf_so/reloc.c | 78 |
1 files changed, 74 insertions, 4 deletions
diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c index 4153db6ad47..dc05fdc2246 100644 --- a/libexec/ld.elf_so/reloc.c +++ b/libexec/ld.elf_so/reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: reloc.c,v 1.36 2001/06/19 01:11:03 fvdl Exp $ */ +/* $NetBSD: reloc.c,v 1.37 2001/07/15 01:44:10 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -77,7 +77,7 @@ _rtld_do_copy_relocation(dstobj, rela, dodebug) unsigned long hash = _rtld_elf_hash(name); size_t size = dstsym->st_size; const void *srcaddr; - const Elf_Sym *srcsym; + const Elf_Sym *srcsym = NULL; Obj_Entry *srcobj; for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) @@ -163,8 +163,8 @@ _rtld_relocate_nonplt_object(obj, rela, dodebug) Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); const Elf_Sym *def; const Obj_Entry *defobj; -#if defined(__alpha__) || defined(__i386__) || defined(__m68k__) || \ - defined(__powerpc__) || defined(__vax__) +#if defined(__alpha__) || defined(__arm__) || defined(__i386__) || \ + defined(__m68k__) || defined(__powerpc__) || defined(__vax__) Elf_Addr tmp; #endif @@ -417,6 +417,76 @@ _rtld_relocate_nonplt_object(obj, rela, dodebug) break; #endif /* __powerpc__ */ +#if defined(__arm__) + case R_TYPE(GLOB_DAT): /* word32 B + S */ + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + *where = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path)); + break; + + case R_TYPE(COPY): + rdbg(dodebug, ("COPY")); + break; + + case R_TYPE(JUMP_SLOT): + rdbg(dodebug, ("JUMP_SLOT")); + break; + + case R_TYPE(ABS32): /* word32 B + S + A */ + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + *where += (Elf_Addr)obj->relocbase + def->st_value; + rdbg(dodebug, ("ABS32 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + *where += (Elf_Addr)obj->relocbase; + rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(PC24): { /* word32 S - P + A */ + Elf32_Sword addend; + + /* + * Extract addend and sign-extend if needed. + */ + addend = *where; + if (addend & 0x00800000) + addend |= 0xff000000; + + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + tmp = (Elf_Addr)obj->relocbase + def->st_value + - (Elf_Addr)where + (addend << 2); + if ((tmp & 0xfe000000) != 0xfe000000 && (tmp & 0xfe000000) != 0) { + _rtld_error( + "%s: R_ARM_PC24 relocation @ %p to %s failed " + "(displacement %ld (%#lx) out of range)", + obj->path, where, defobj->strtab + def->st_name, + (long) tmp, (long) tmp); + return -1; + } + tmp >>= 2; + *where = (*where & 0xff000000) | (tmp & 0x00ffffff); + rdbg(dodebug, ("PC24 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path)); + break; + } +#endif + default: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, true); |
