diff options
| author | martin <martin@NetBSD.org> | 2019-12-09 16:14:10 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2019-12-09 16:14:10 +0000 |
| commit | e5628491ec591c8a805cbb4a36f81102be09554a (patch) | |
| tree | 11a88191cfe6d26a9ba0d8ec82d5ebce4e145f81 /libexec | |
| parent | 3d17a8c56a756d5dd5624ca34299107c9bbb7e54 (diff) | |
Pull up following revision(s) (requested by uwe in ticket #535):
libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.60
libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.59
Resolve ADDR16_LO, ADDR16_HI, and ADDR16_HA relocs.
Recent GNU ld does not resolve them statically if the reloc is in a
writable section and the symbol is not already referenced from text.
Use existing lo() and hi() macros. Same object code is generated.
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c index 83974c6e1da..b3fb4c1bf4c 100644 --- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c +++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ppc_reloc.c,v 1.58 2018/12/30 03:23:46 christos Exp $ */ +/* $NetBSD: ppc_reloc.c,v 1.58.2.1 2019/12/09 16:14:10 martin Exp $ */ /*- * Copyright (C) 1998 Tsubai Masanari @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: ppc_reloc.c,v 1.58 2018/12/30 03:23:46 christos Exp $"); +__RCSID("$NetBSD: ppc_reloc.c,v 1.58.2.1 2019/12/09 16:14:10 martin Exp $"); #endif /* not lint */ #include <stdarg.h> @@ -197,6 +197,9 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj) case R_TYPE(ADDR32): /* <address> S + A */ #endif case R_TYPE(GLOB_DAT): /* <address> S + A */ + case R_TYPE(ADDR16_LO): + case R_TYPE(ADDR16_HI): + case R_TYPE(ADDR16_HA): case R_TYPE(DTPMOD): case R_TYPE(DTPREL): case R_TYPE(TPREL): @@ -234,6 +237,50 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj) obj->path, (void *)*where, defobj->path)); break; + /* + * Recent GNU ld does not resolve ADDR16_{LO,HI,HA} if + * the reloc is in a writable section and the symbol + * is not already referenced from text. + */ + case R_TYPE(ADDR16_LO): { + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + + uint16_t tmp16 = lo(tmp); + + uint16_t *where16 = (uint16_t *)where; + if (*where16 != tmp16) + *where16 = tmp16; + rdbg(("ADDR16_LO %s in %s --> #lo(%p) = 0x%x in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp, tmp16, defobj->path)); + break; + } + + case R_TYPE(ADDR16_HI): + case R_TYPE(ADDR16_HA): { + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + + uint16_t tmp16 = hi(tmp); + if (ELF_R_TYPE(rela->r_info) == R_TYPE(ADDR16_HA) + && (tmp & __ha16)) + ++tmp16; /* adjust to ha(tmp) */ + + uint16_t *where16 = (uint16_t *)where; + if (*where16 != tmp16) + *where16 = tmp16; + rdbg(("ADDR16_H%c %s in %s --> #h%c(%p) = 0x%x in %s", + (ELF_R_TYPE(rela->r_info) == R_TYPE(ADDR16_HI) + ? 'I' : 'A'), + obj->strtab + obj->symtab[symnum].st_name, + obj->path, + (ELF_R_TYPE(rela->r_info) == R_TYPE(ADDR16_HI) + ? 'i' : 'a'), + (void *)tmp, tmp16, defobj->path)); + break; + } + case R_TYPE(RELATIVE): /* <address> B + A */ *where = (Elf_Addr)(obj->relocbase + rela->r_addend); rdbg(("RELATIVE in %s --> %p", obj->path, |
