From f5794e1a317089f9316dc30f83fce12dccea0342 Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund <joakim.tjernlund@transmode.se>
Date: Thu, 10 Mar 2005 16:29:22 +0000
Subject: Use DT_RELCONT_IDX to optimize the relocation of R_PPC_RELATIVE
 relocs. All RELA arches can probably copy this. REL archs will have to delete
 the "+ rpnt->r_addend" from the loop.

---
 ldso/ldso/powerpc/elfinterp.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c
index 8175a0178..d3dd269fe 100644
--- a/ldso/ldso/powerpc/elfinterp.c
+++ b/ldso/ldso/powerpc/elfinterp.c
@@ -421,7 +421,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
 			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
-	unsigned int i;
+	unsigned int i, relative_count;
 	char *strtab;
 	Elf32_Sym *symtab;
 	ELF_RELOC *rpnt;
@@ -433,6 +433,18 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 
 	symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	
+	relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+	if (relative_count) { /* Optimize the  R_PPC_RELATIVE relocations if possible */
+		Elf32_Addr loadaddr = tpnt->loadaddr;
+		rel_size -= relative_count;
+		--rpnt;
+		do {     /* PowerPC handles pre increment/decrement better */ 
+			Elf32_Addr *const reloc_addr = (void *) (loadaddr + (++rpnt)->r_offset);
+
+			*reloc_addr =  loadaddr + rpnt->r_addend;
+		} while (--relative_count);
+	}
 
 	  for (i = 0; i < rel_size; i++, rpnt++) {
 	        int res;
-- 
cgit v1.2.3