Page MenuHomeFreeBSD

D54246.id168173.diff
No OneTemporary

D54246.id168173.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,38 @@
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 + phdrl->p_vaddr >= addr &&
+ addr < obj->relocbase + phdrl->p_vaddr + phdrl->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 = obj->phsize / sizeof(*phdr), phdrl = obj->phdr;
+ c > 0; c--, phdrl++) {
+ if (phdrl->p_type == PT_LOAD &&
+ is_where_in_phdr(obj, phdrl, addr))
+ return (phdrl);
+ }
+ return (NULL);
+}
/*
* Process non-PLT relocations
@@ -327,7 +367,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,11 +393,24 @@
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);
@@ -368,8 +422,6 @@
(const char *)phdr < (const char *)obj->phdr + obj->phsize;
phdr++) {
if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) {
- __syncicache(obj->relocbase + phdr->p_vaddr,
- phdr->p_memsz);
}
}

File Metadata

Mime Type
text/plain
Expires
Mon, May 18, 12:22 PM (8 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33248153
Default Alt Text
D54246.id168173.diff (3 KB)

Event Timeline