summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>2000-05-22 16:31:18 +0000
committerjdp <jdp@FreeBSD.org>2000-05-22 16:31:18 +0000
commitb1fe210efcf39b4d1bd890a6835a37515aa3643c (patch)
tree5c12d7a854aef817f702513230aa1d8b81656cab /libexec
parent4e9d022872d5646eddc9a6321d0b7ca70f61bb2b (diff)
downloadFreeBSD-src-b1fe210efcf39b4d1bd890a6835a37515aa3643c.zip
FreeBSD-src-b1fe210efcf39b4d1bd890a6835a37515aa3643c.tar.gz
Eliminate unaligned accesses that occurred when relocating the
DWARF2 exception tables emitted by the compiler for C++ sources. These tables are tightly packed, and they contain some relocated addresses which are not well-aligned.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/alpha/reloc.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/libexec/rtld-elf/alpha/reloc.c b/libexec/rtld-elf/alpha/reloc.c
index 8763be4..e27f922 100644
--- a/libexec/rtld-elf/alpha/reloc.c
+++ b/libexec/rtld-elf/alpha/reloc.c
@@ -49,6 +49,23 @@
extern Elf_Dyn _DYNAMIC;
+/*
+ * Macros for loading/storing unaligned 64-bit values. These are
+ * needed because relocations can point to unaligned data. This
+ * occurs in the DWARF2 exception frame tables generated by the
+ * compiler, for instance.
+ *
+ * We don't use these when relocating jump slots and GOT entries,
+ * since they are guaranteed to be aligned.
+ */
+#define load64(p) ({ \
+ Elf_Addr __res; \
+ __asm__("ldq_u %0,%1" : "=r"(__res) : "m"(*(p))); \
+ __res; })
+
+#define store64(p, v) \
+ __asm__("stq_u %1,%0" : "=m"(*(p)) : "r"(v))
+
/* Relocate a non-PLT object with addend. */
static int
reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela)
@@ -63,33 +80,30 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela)
case R_ALPHA_REFQUAD: {
const Elf_Sym *def;
const Obj_Entry *defobj;
- Elf_Addr tmp_value;
def = find_symdef(ELF_R_SYM(rela->r_info), obj,
&defobj, false);
if (def == NULL)
return -1;
-
- tmp_value = (Elf_Addr) (defobj->relocbase +
- def->st_value) + *where + rela->r_addend;
- if (*where != tmp_value)
- *where = tmp_value;
+ store64(where,
+ (Elf_Addr) (defobj->relocbase + def->st_value) +
+ load64(where) + rela->r_addend);
}
break;
case R_ALPHA_GLOB_DAT: {
const Elf_Sym *def;
const Obj_Entry *defobj;
+ Elf_Addr val;
def = find_symdef(ELF_R_SYM(rela->r_info), obj,
&defobj, false);
if (def == NULL)
return -1;
-
- if (*where != (Elf_Addr) (defobj->relocbase +
- def->st_value + rela->r_addend))
- *where = (Elf_Addr) (defobj->relocbase +
- def->st_value + rela->r_addend);
+ val = (Elf_Addr) (defobj->relocbase + def->st_value +
+ rela->r_addend);
+ if (load64(where) != val)
+ store64(where, val);
}
break;
@@ -97,7 +111,8 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela)
if (obj != obj_rtld ||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)&_DYNAMIC)
- *where += (Elf_Addr) obj->relocbase;
+ store64(where,
+ load64(where) + (Elf_Addr) obj->relocbase);
}
break;
OpenPOWER on IntegriCloud