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.
This commit is contained in:
John Polstra 2000-05-22 16:31:18 +00:00
parent 4f14ee00f2
commit a0f2601e13
1 changed files with 27 additions and 12 deletions

View File

@ -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;