Page MenuHomeFreeBSD

D54246.diff
No OneTemporary

D54246.diff

diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c
--- a/libexec/rtld-elf/powerpc64/reloc.c
+++ b/libexec/rtld-elf/powerpc64/reloc.c
@@ -168,11 +168,13 @@
*/
static int
reloc_nonplt_object(Obj_Entry *obj_rtld __unused, Obj_Entry *obj,
- const Elf_Rela *rela, SymCache *cache, int flags, RtldLockState *lockstate)
+ const Elf_Rela *rela, SymCache *cache, int flags, RtldLockState *lockstate,
+ Elf_Addr **wherep)
{
const Elf_Sym *def = NULL;
const Obj_Entry *defobj;
- Elf_Addr *where, symval = 0;
+ Elf_Addr symval = 0;
+ Elf_Addr *where;
/*
* First, resolve symbol for relocations which
@@ -235,6 +237,7 @@
switch (ELF_R_TYPE(rela->r_info)) {
case R_PPC_NONE:
+ *wherep = NULL;
break;
case R_PPC64_UADDR64:
case R_PPC64_ADDR64:
@@ -243,9 +246,11 @@
if (*where != symval + rela->r_addend) {
*where = symval + rela->r_addend;
}
+ *wherep = where;
break;
case R_PPC64_DTPMOD64:
*where = (Elf_Addr) defobj->tlsindex;
+ *wherep = where;
break;
case R_PPC64_TPREL64:
/*
@@ -268,10 +273,12 @@
*(Elf_Addr **)where = *where * sizeof(Elf_Addr)
+ (Elf_Addr *)(def->st_value + rela->r_addend
+ defobj->tlsoffset - TLS_TP_OFFSET - TLS_TCB_SIZE);
+ *wherep = where;
break;
case R_PPC64_DTPREL64:
*where += (Elf_Addr)(def->st_value + rela->r_addend
- TLS_DTV_OFFSET);
+ *wherep = where;
break;
case R_PPC_RELATIVE: /* doubleword64 B + A */
symval = (Elf_Addr)(obj->relocbase + rela->r_addend);
@@ -280,6 +287,7 @@
if (*where != symval) {
*where = symval;
}
+ *wherep = where;
break;
case R_PPC_COPY:
/*
@@ -295,17 +303,20 @@
obj->path);
return (-1);
}
+ *wherep = NULL;
break;
case R_PPC_IRELATIVE:
/*
* These will be handled by reloc_iresolve().
*/
obj->irelative = true;
+ *wherep = NULL;
break;
case R_PPC_JMP_SLOT:
/*
* These will be handled by the plt/jmpslot routines
*/
+ *wherep = NULL;
break;
default:
@@ -314,9 +325,37 @@
ELF_R_TYPE(rela->r_info));
return (-1);
}
+ *wherep = where;
return (0);
}
+static void
+phdr_syncicache(Obj_Entry *obj, const Elf_Phdr *phdr)
+{
+ if ((phdr->p_flags & PF_X) != 0)
+ __syncicache(obj->relocbase + phdr->p_vaddr, phdr->p_memsz);
+}
+
+static bool
+is_addr_in_phdr(Obj_Entry *obj, const Elf_Phdr *phdr, Elf_Addr addr)
+{
+ return (obj->relocbase + phdr->p_vaddr >= (caddr_t)addr &&
+ (caddr_t)addr < obj->relocbase + phdr->p_vaddr + phdr->p_memsz);
+}
+
+static const Elf_Phdr *
+find_phdr_from_addr(Obj_Entry *obj, Elf_Addr addr)
+{
+ const Elf_Phdr *phdr = NULL;
+ size_t c;
+
+ for (c = 0, phdr = obj->phdr; c < obj->phnum; c++, phdr++) {
+ if (phdr->p_type == PT_LOAD &&
+ is_addr_in_phdr(obj, phdr, addr))
+ return (phdr);
+ }
+ return (NULL);
+}
/*
* Process non-PLT relocations
@@ -327,7 +366,8 @@
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
- const Elf_Phdr *phdr;
+ const Elf_Phdr *phdr = NULL;
+ Elf_Addr *where;
SymCache *cache;
int bytes = obj->dynsymcount * sizeof(SymCache);
int r = -1;
@@ -352,25 +392,27 @@
relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize);
for (rela = obj->rela; rela < relalim; rela++) {
if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags,
- lockstate) < 0)
+ lockstate, &where) < 0)
goto done;
+ if (where != NULL) {
+ if (phdr != NULL &&
+ !is_addr_in_phdr(obj, phdr, (Elf_Addr)where)) {
+ phdr_syncicache(obj, phdr);
+ phdr = NULL;
+ }
+ if (phdr == NULL) {
+ phdr = find_phdr_from_addr(obj,
+ (Elf_Addr)where);
+ }
+ }
}
r = 0;
done:
+ if (phdr != NULL)
+ phdr_syncicache(obj, phdr);
if (cache)
munmap(cache, bytes);
- /*
- * Synchronize icache for executable segments in case we made
- * any changes.
- */
- for (phdr = obj->phdr; phdr < obj->phdr + obj->phnum; phdr++) {
- if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) {
- __syncicache(obj->relocbase + phdr->p_vaddr,
- phdr->p_memsz);
- }
- }
-
return (r);
}

File Metadata

Mime Type
text/plain
Expires
Fri, May 15, 12:53 AM (11 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33068883
Default Alt Text
D54246.diff (3 KB)

Event Timeline