Module Name:    src
Committed By:   uwe
Date:           Sun Dec  8 22:57:51 UTC 2019

Modified Files:
        src/libexec/ld.elf_so/arch/powerpc: ppc_reloc.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
diff -u src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.58 src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.59
--- src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c:1.58	Sun Dec 30 03:23:46 2018
+++ src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c	Sun Dec  8 22:57:51 2019
@@ -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.59 2019/12/08 22:57:51 uwe 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.59 2019/12/08 22:57:51 uwe Exp $");
 #endif /* not lint */
 
 #include <stdarg.h>
@@ -197,6 +197,9 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
 		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->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 = (uint16_t)(tmp & 0xffff);
+
+			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 = (uint16_t)((tmp >> 16) & 0xffff);
+			if (ELF_R_TYPE(rela->r_info) == R_TYPE(ADDR16_HA)
+			    && (tmp & 0x8000))
+				++tmp16;
+
+			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,

Reply via email to