From b1fe210efcf39b4d1bd890a6835a37515aa3643c Mon Sep 17 00:00:00 2001 From: jdp Date: Mon, 22 May 2000 16:31:18 +0000 Subject: 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. --- libexec/rtld-elf/alpha/reloc.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'libexec') 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; -- cgit v1.1