Split _rtld_relocate_nonplt_object() into separate MD files.

This commit is contained in:
mycroft 2002-09-05 18:25:45 +00:00
parent b4a8cd2dbf
commit 00c3ad1f56
12 changed files with 1052 additions and 712 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: alpha_reloc.c,v 1.4 2002/09/05 15:38:23 mycroft Exp $ */
/* $NetBSD: alpha_reloc.c,v 1.5 2002/09/05 18:25:46 mycroft Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -107,3 +107,98 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
__asm __volatile("imb");
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(REFQUAD):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
*where + rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("REFQUAD %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(GLOB_DAT):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
{
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Addr _GOT_END_[];
/* This is the ...iffy hueristic. */
if (!dodebug ||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)_GOT_END_) {
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
} else
rdbg(dodebug, ("RELATIVE in %s stays at %p",
obj->path, (void *)*where));
break;
}
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -10,3 +10,112 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
#if 1 /* XXX should not occur */
case R_TYPE(PC24): { /* word32 S - P + A */
Elf32_Sword addend;
/*
* Extract addend and sign-extend if needed.
*/
addend = *where;
if (addend & 0x00800000)
addend |= 0xff000000;
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)obj->relocbase + def->st_value
- (Elf_Addr)where + (addend << 2);
if ((tmp & 0xfe000000) != 0xfe000000 &&
(tmp & 0xfe000000) != 0) {
_rtld_error(
"%s: R_ARM_PC24 relocation @ %p to %s failed "
"(displacement %ld (%#lx) out of range)",
obj->path, where, defobj->strtab + def->st_name,
(long) tmp, (long) tmp);
return -1;
}
tmp >>= 2;
*where = (*where & 0xff000000) | (tmp & 0x00ffffff);
rdbg(dodebug, ("PC24 %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
}
#endif
case R_TYPE(ABS32): /* word32 B + S + A */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)defobj->relocbase + def->st_value;
rdbg(dodebug, ("ABS32 %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
case R_TYPE(GLOB_DAT): /* word32 B + S */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p @ %p", obj->path,
(void *)*where, where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hppa_reloc.c,v 1.3 2002/09/05 16:33:57 junyoung Exp $ */
/* $NetBSD: hppa_reloc.c,v 1.4 2002/09/05 18:25:46 mycroft Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -333,3 +333,146 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
{
__rtld_setup_hppa_pltgot(obj, HPPA_OBJ_GOT(obj));
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(DIR32):
if (ELF_R_SYM(rela->r_info)) {
/*
* This is either a DIR32 against a symbol
* (def->st_name != 0), or against a local
* section (def->st_name == 0).
*/
def = obj->symtab + ELF_R_SYM(rela->r_info);
defobj = obj;
if (def->st_name != 0)
/*
* While we're relocating self, _rtld_objlist
* is NULL, so we just pass in self.
*/
def = _rtld_find_symdef(rela->r_info, obj,
&defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("DIR32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
} else {
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Addr _GOT_END_[];
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
/* This is the ...iffy hueristic. */
if (!dodebug ||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)_GOT_END_) {
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("DIR32 in %s --> %p", obj->path,
(void *)*where));
} else
rdbg(dodebug, ("DIR32 in %s stays at %p",
obj->path, (void *)*where));
}
break;
case R_TYPE(PLABEL32):
if (ELF_R_SYM(rela->r_info)) {
/*
* While we're relocating self, _rtld_objlist
* is NULL, so we just pass in self.
*/
def = _rtld_find_symdef(rela->r_info, obj, &defobj,
false);
if (def == NULL)
return -1;
tmp = _rtld_function_descriptor_alloc(defobj, def,
rela->r_addend);
if (tmp == (Elf_Addr)-1)
return -1;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PLABEL32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
} else {
/*
* This is a PLABEL for a static function, and the
* dynamic linker has both allocated a PLT entry
* for this function and told us where it is. We
* can safely use the PLT entry as the PLABEL
* because there should be no other PLABEL reloc
* referencing this function. This object should
* also have an IPLT relocation to initialize the
* PLT entry.
*
* The dynamic linker should also have ensured
* that the addend has the next-least-significant
* bit set; the $$dyncall millicode uses this to
* distinguish a PLABEL pointer from a plain
* function pointer.
*/
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PLABEL32 in %s --> %p",
obj->path, (void *)*where));
}
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -10,3 +10,88 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
#if 1 /* XXX should not occur */
case R_TYPE(PC32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value) -
(Elf_Addr)where;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(GOT32):
#endif
case R_TYPE(32):
case R_TYPE(GLOB_DAT):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -10,3 +10,90 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
#if 1 /* XXX should not occur */
case R_TYPE(PC32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend) - (Elf_Addr)where;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(GOT32):
#endif
case R_TYPE(32):
case R_TYPE(GLOB_DAT):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ppc_reloc.c,v 1.12 2002/09/05 16:33:58 junyoung Exp $ */
/* $NetBSD: ppc_reloc.c,v 1.13 2002/09/05 18:25:47 mycroft Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@ -181,3 +181,75 @@ _rtld_setup_pltgot(obj)
__syncicache(pltcall, 72 + N * 8);
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(32): /* word32 S + A */
case R_TYPE(GLOB_DAT): /* word32 S + A */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -10,3 +10,115 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
#if 1 /* XXX should not occur */
case R_TYPE(GOT32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(REL32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend) - (Elf_Addr)where;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
#endif
case R_TYPE(DIR32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
rdbg(dodebug, ("32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(GLOB_DAT):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
if (rela->r_addend)
*where = (Elf_Addr)obj->relocbase + rela->r_addend;
else
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.12 2002/09/05 16:33:58 junyoung Exp $ */
/* $NetBSD: mdreloc.c,v 1.13 2002/09/05 18:25:47 mycroft Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -160,6 +160,85 @@ static int reloc_target_bitmask[] = {
};
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
int
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
caddr_t *addrp;
bool bind_now;
bool dodebug;
{
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf_Addr value;
if (bind_now == 0 && obj->pltgot != NULL)
return (0);
/* Fully resolve procedure addresses now */
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
if (def == NULL)
return (-1);
value = (Elf_Addr) (defobj->relocbase + def->st_value);
rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
(int)bind_now, defobj->strtab + def->st_name,
(void *)*where, (void *)value));
/*
* At the PLT entry pointed at by `where', we now construct
* a direct transfer to the now fully resolved function
* address. The resulting code in the jump slot is:
*
* sethi %hi(roffset), %g1
* sethi %hi(addr), %g1
* jmp %g1+%lo(addr)
*
* We write the third instruction first, since that leaves the
* previous `b,a' at the second word in place. Hence the whole
* PLT slot can be atomically change to the new sequence by
* writing the `sethi' instruction at word 2.
*/
#define SETHI 0x03000000
#define JMP 0x81c06000
#define NOP 0x01000000
where[2] = JMP | (value & 0x000003ff);
where[1] = SETHI | ((value >> 10) & 0x003fffff);
__asm __volatile("iflush %0+8" : : "r" (where));
__asm __volatile("iflush %0+4" : : "r" (where));
if (addrp != NULL)
*addrp = (caddr_t)value;
return (0);
}
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
/*
* PLTGOT is the PLT on the sparc.
* The first entry holds the call the dynamic linker.
* We construct a `call' sequence that transfers
* to `_rtld_bind_start()'.
* The second entry holds the object identification.
* Note: each PLT entry is three words long.
*/
#define SAVE 0x9de3bfc0 /* i.e. `save %sp,-64,%sp' */
#define CALL 0x40000000
#define NOP 0x01000000
obj->pltgot[0] = SAVE;
obj->pltgot[1] = CALL |
((Elf_Addr) &_rtld_bind_start - (Elf_Addr) &obj->pltgot[1]) >> 2;
obj->pltgot[2] = NOP;
obj->pltgot[3] = (Elf_Addr) obj;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
@ -260,82 +339,3 @@ _rtld_relocate_nonplt_object(obj, rela, dodebug)
#endif
return (0);
}
int
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
caddr_t *addrp;
bool bind_now;
bool dodebug;
{
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf_Addr value;
if (bind_now == 0 && obj->pltgot != NULL)
return (0);
/* Fully resolve procedure addresses now */
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
if (def == NULL)
return (-1);
value = (Elf_Addr) (defobj->relocbase + def->st_value);
rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
(int)bind_now, defobj->strtab + def->st_name,
(void *)*where, (void *)value));
/*
* At the PLT entry pointed at by `where', we now construct
* a direct transfer to the now fully resolved function
* address. The resulting code in the jump slot is:
*
* sethi %hi(roffset), %g1
* sethi %hi(addr), %g1
* jmp %g1+%lo(addr)
*
* We write the third instruction first, since that leaves the
* previous `b,a' at the second word in place. Hence the whole
* PLT slot can be atomically change to the new sequence by
* writing the `sethi' instruction at word 2.
*/
#define SETHI 0x03000000
#define JMP 0x81c06000
#define NOP 0x01000000
where[2] = JMP | (value & 0x000003ff);
where[1] = SETHI | ((value >> 10) & 0x003fffff);
__asm __volatile("iflush %0+8" : : "r" (where));
__asm __volatile("iflush %0+4" : : "r" (where));
if (addrp != NULL)
*addrp = (caddr_t)value;
return (0);
}
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
/*
* PLTGOT is the PLT on the sparc.
* The first entry holds the call the dynamic linker.
* We construct a `call' sequence that transfers
* to `_rtld_bind_start()'.
* The second entry holds the object identification.
* Note: each PLT entry is three words long.
*/
#define SAVE 0x9de3bfc0 /* i.e. `save %sp,-64,%sp' */
#define CALL 0x40000000
#define NOP 0x01000000
obj->pltgot[0] = SAVE;
obj->pltgot[1] = CALL |
((Elf_Addr) &_rtld_bind_start - (Elf_Addr) &obj->pltgot[1]) >> 2;
obj->pltgot[2] = NOP;
obj->pltgot[3] = (Elf_Addr) obj;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.7 2002/09/05 16:33:58 junyoung Exp $ */
/* $NetBSD: mdreloc.c,v 1.8 2002/09/05 18:25:47 mycroft Exp $ */
/*-
* Copyright (c) 2000 Eduardo Horvath.
@ -184,143 +184,6 @@ static long reloc_target_bitmask[] = {
};
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf_Word type;
Elf_Addr value = 0, mask;
const Elf_Sym *def = NULL;
const Obj_Entry *defobj = NULL;
type = ELF_R_TYPE(rela->r_info);
if (type == R_TYPE(NONE))
return (0);
/* We do JMP_SLOTs in relocate_plt_object() below */
if (type == R_TYPE(JMP_SLOT))
return (0);
/* COPY relocs are also handled elsewhere */
if (type == R_TYPE(COPY))
return (0);
/*
* We use the fact that relocation types are an `enum'
* Note: R_SPARC_UA16 is currently numerically largest.
*/
if (type > R_TYPE(UA16))
return (-1);
value = rela->r_addend;
/*
* Handle relative relocs here, because we might not
* be able to access globals yet.
*/
if (!dodebug && type == R_TYPE(RELATIVE)) {
/* XXXX -- apparently we ignore the preexisting value */
*where = (Elf_Addr)(obj->relocbase + value);
return (0);
}
if (RELOC_RESOLVE_SYMBOL(type)) {
/* Find the symbol */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return (-1);
/* Add in the symbol's absolute address */
value += (Elf_Addr)(defobj->relocbase + def->st_value);
}
if (RELOC_PC_RELATIVE(type)) {
value -= (Elf_Addr)where;
}
if (RELOC_BASE_RELATIVE(type)) {
/*
* Note that even though sparcs use `Elf_rela' exclusively
* we still need the implicit memory addend in relocations
* referring to GOT entries. Undoubtedly, someone f*cked
* this up in the distant past, and now we're stuck with
* it in the name of compatibility for all eternity..
*
* In any case, the implicit and explicit should be mutually
* exclusive. We provide a check for that here.
*/
#ifdef DIAGNOSTIC
if (value != 0 && *where != 0) {
xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
"addend=0x%lx, base %p\n",
obj->path, where, *where,
rela->r_addend, obj->relocbase);
}
#endif
/* XXXX -- apparently we ignore the preexisting value */
value += (Elf_Addr)(obj->relocbase);
}
mask = RELOC_VALUE_BITMASK(type);
value >>= RELOC_VALUE_RIGHTSHIFT(type);
value &= mask;
if (RELOC_UNALIGNED(type)) {
/* Handle unaligned relocations. */
Elf_Addr tmp = 0;
char *ptr = (char *)where;
int i, size = RELOC_TARGET_SIZE(type)/8;
/* Read it in one byte at a time. */
for (i=0; i<size; i++)
tmp = (tmp << 8) | ptr[i];
tmp &= ~mask;
tmp |= value;
/* Write it back out. */
for (i=0; i<size; i++)
ptr[i] = ((tmp >> (8*i)) & 0xff);
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)tmp;
#endif
} else if (RELOC_TARGET_SIZE(type) > 32) {
*where &= ~mask;
*where |= value;
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)*where;
#endif
} else {
Elf32_Addr *where32 = (Elf32_Addr *)where;
*where32 &= ~mask;
*where32 |= value;
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)*where32;
#endif
}
#ifdef RTLD_DEBUG_RELOC
if (RELOC_RESOLVE_SYMBOL(type)) {
rdbg(dodebug, ("%s %s in %s --> %p %s",
reloc_names[type],
defobj->strtab + def->st_name, obj->path,
(void *)value, defobj->path));
}
else {
rdbg(dodebug, ("%s --> %p", reloc_names[type],
(void *)value));
}
#endif
return (0);
}
/*
* Instruction templates:
*/
@ -656,3 +519,139 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[8] = (Elf_Addr) obj;
}
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf_Word type;
Elf_Addr value = 0, mask;
const Elf_Sym *def = NULL;
const Obj_Entry *defobj = NULL;
type = ELF_R_TYPE(rela->r_info);
if (type == R_TYPE(NONE))
return (0);
/* We do JMP_SLOTs in relocate_plt_object() below */
if (type == R_TYPE(JMP_SLOT))
return (0);
/* COPY relocs are also handled elsewhere */
if (type == R_TYPE(COPY))
return (0);
/*
* We use the fact that relocation types are an `enum'
* Note: R_SPARC_UA16 is currently numerically largest.
*/
if (type > R_TYPE(UA16))
return (-1);
value = rela->r_addend;
/*
* Handle relative relocs here, because we might not
* be able to access globals yet.
*/
if (!dodebug && type == R_TYPE(RELATIVE)) {
/* XXXX -- apparently we ignore the preexisting value */
*where = (Elf_Addr)(obj->relocbase + value);
return (0);
}
if (RELOC_RESOLVE_SYMBOL(type)) {
/* Find the symbol */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return (-1);
/* Add in the symbol's absolute address */
value += (Elf_Addr)(defobj->relocbase + def->st_value);
}
if (RELOC_PC_RELATIVE(type)) {
value -= (Elf_Addr)where;
}
if (RELOC_BASE_RELATIVE(type)) {
/*
* Note that even though sparcs use `Elf_rela' exclusively
* we still need the implicit memory addend in relocations
* referring to GOT entries. Undoubtedly, someone f*cked
* this up in the distant past, and now we're stuck with
* it in the name of compatibility for all eternity..
*
* In any case, the implicit and explicit should be mutually
* exclusive. We provide a check for that here.
*/
#ifdef DIAGNOSTIC
if (value != 0 && *where != 0) {
xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
"addend=0x%lx, base %p\n",
obj->path, where, *where,
rela->r_addend, obj->relocbase);
}
#endif
/* XXXX -- apparently we ignore the preexisting value */
value += (Elf_Addr)(obj->relocbase);
}
mask = RELOC_VALUE_BITMASK(type);
value >>= RELOC_VALUE_RIGHTSHIFT(type);
value &= mask;
if (RELOC_UNALIGNED(type)) {
/* Handle unaligned relocations. */
Elf_Addr tmp = 0;
char *ptr = (char *)where;
int i, size = RELOC_TARGET_SIZE(type)/8;
/* Read it in one byte at a time. */
for (i=0; i<size; i++)
tmp = (tmp << 8) | ptr[i];
tmp &= ~mask;
tmp |= value;
/* Write it back out. */
for (i=0; i<size; i++)
ptr[i] = ((tmp >> (8*i)) & 0xff);
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)tmp;
#endif
} else if (RELOC_TARGET_SIZE(type) > 32) {
*where &= ~mask;
*where |= value;
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)*where;
#endif
} else {
Elf32_Addr *where32 = (Elf32_Addr *)where;
*where32 &= ~mask;
*where32 |= value;
#ifdef RTLD_DEBUG_RELOC
value = (Elf_Addr)*where32;
#endif
}
#ifdef RTLD_DEBUG_RELOC
if (RELOC_RESOLVE_SYMBOL(type)) {
rdbg(dodebug, ("%s %s in %s --> %p %s",
reloc_names[type],
defobj->strtab + def->st_name, obj->path,
(void *)value, defobj->path));
}
else {
rdbg(dodebug, ("%s --> %p", reloc_names[type],
(void *)value));
}
#endif
return (0);
}

View File

@ -10,3 +10,76 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(32): /* word32 S + A */
case R_TYPE(GLOB_DAT): /* word32 S + A */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.7 2002/09/05 16:33:58 junyoung Exp $ */
/* $NetBSD: mdreloc.c,v 1.8 2002/09/05 18:25:48 mycroft Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -83,6 +83,60 @@
extern Elf64_Addr _GLOBAL_OFFSET_TABLE_[];
int
_rtld_relocate_plt_object(Obj_Entry *obj, const Elf_Rela *rela, caddr_t *addrp,
bool bind_now, bool dodebug)
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
Elf_Addr new_value;
/* Fully resolve procedure addresses now */
if (bind_now || obj->pltgot == NULL) {
const Elf_Sym *def;
const Obj_Entry *defobj;
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT));
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
if (def == NULL)
return -1;
new_value = (Elf_Addr)
(defobj->relocbase + def->st_value + rela->r_addend);
rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
(int)bind_now,
defobj->strtab + def->st_name,
(void *)*where, (void *)new_value));
} else {
if (!obj->mainprog) {
/* Just relocate the GOT slots pointing into the PLT */
new_value = *where + (Elf_Addr) obj->relocbase;
rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
(void *)(unsigned long)*where));
} else {
return 0;
}
}
/*
* Since this page is probably copy-on-write, let's not write
* it unless we really really have to.
*/
if (*where != new_value)
*where = new_value;
if (addrp != NULL)
*addrp = *(caddr_t *)(obj->relocbase + rela->r_offset) -
rela->r_addend;
return 0;
}
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
int
_rtld_relocate_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, bool dodebug)
{
@ -183,59 +237,3 @@ _rtld_relocate_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, bool dodebug)
}
return 0;
}
int
_rtld_relocate_plt_object(Obj_Entry *obj, const Elf_Rela *rela, caddr_t *addrp,
bool bind_now, bool dodebug)
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
Elf_Addr new_value;
/* Fully resolve procedure addresses now */
if (bind_now || obj->pltgot == NULL) {
const Elf_Sym *def;
const Obj_Entry *defobj;
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT));
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
if (def == NULL)
return -1;
new_value = (Elf_Addr)
(defobj->relocbase + def->st_value + rela->r_addend);
rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
(int)bind_now,
defobj->strtab + def->st_name,
(void *)*where, (void *)new_value));
} else {
if (!obj->mainprog) {
/* Just relocate the GOT slots pointing into the PLT */
new_value = *where + (Elf_Addr) obj->relocbase;
rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
(void *)(unsigned long)*where));
} else {
return 0;
}
}
/*
* Since this page is probably copy-on-write, let's not write
* it unless we really really have to.
*/
if (*where != new_value)
*where = new_value;
if (addrp != NULL)
*addrp = *(caddr_t *)(obj->relocbase + rela->r_offset) -
rela->r_addend;
return 0;
}
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: reloc.c,v 1.58 2002/09/05 17:58:02 mycroft Exp $ */
/* $NetBSD: reloc.c,v 1.59 2002/09/05 18:25:45 mycroft Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -149,439 +149,6 @@ _rtld_do_copy_relocations(dstobj, dodebug)
#if !defined(__sparc__) && !defined(__x86_64__) && !defined(__mips__)
int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
Obj_Entry *obj;
const Elf_Rela *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
#if defined(__i386__)
case R_TYPE(GOT32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(PC32):
/*
* I don't think the dynamic linker should ever see this
* type of relocation. But the binutils-2.6 tools sometimes
* generate it.
*/
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value) -
(Elf_Addr)where;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, ("32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
#endif /* __i386__ */
#if defined(__m68k__)
case R_TYPE(GOT32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(PC32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend) - (Elf_Addr)where;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
#endif /* __m68k__ */
#if defined(__sh__)
case R_TYPE(GOT32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(REL32):
/*
* I don't think the dynamic linker should ever see this
* type of relocation, but some versions of Binutils
* generate it.
*/
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend) - (Elf_Addr)where;
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(DIR32):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
rdbg(dodebug, ("32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
#endif /* __sh__ */
#if defined(__alpha__)
case R_TYPE(REFQUAD):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
*where + rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("REFQUAD %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
{
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Addr _GOT_END_[];
/* This is the ...iffy hueristic. */
if (!dodebug ||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)_GOT_END_) {
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
} else
rdbg(dodebug, ("RELATIVE in %s stays at %p",
obj->path, (void *)*where));
break;
}
#endif /* __alpha__ */
#if defined(__alpha__) || defined(__i386__) || defined(__m68k__) || \
defined(__sh__)
case R_TYPE(GLOB_DAT):
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
#if defined(__sh__)
case R_TYPE(RELATIVE):
if (rela->r_addend)
*where = (Elf_Addr)obj->relocbase + rela->r_addend;
else
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
#elif !defined(__alpha__)
case R_TYPE(RELATIVE):
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
#endif /* ! __alpha__ */
#endif /* __alpha__ || __i386__ || __m68k__ || __sh__ */
#if defined(__powerpc__) || defined(__vax__)
case R_TYPE(32): /* word32 S + A */
case R_TYPE(GLOB_DAT): /* word32 S + A */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
#endif /* __powerpc__ || __vax__ */
#if defined(__arm__)
case R_TYPE(GLOB_DAT): /* word32 B + S */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
case R_TYPE(ABS32): /* word32 B + S + A */
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
*where += (Elf_Addr)defobj->relocbase + def->st_value;
rdbg(dodebug, ("ABS32 %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, ("RELATIVE in %s --> %p @ %p", obj->path,
(void *)*where, where));
break;
case R_TYPE(PC24): { /* word32 S - P + A */
Elf32_Sword addend;
/*
* Extract addend and sign-extend if needed.
*/
addend = *where;
if (addend & 0x00800000)
addend |= 0xff000000;
def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)obj->relocbase + def->st_value
- (Elf_Addr)where + (addend << 2);
if ((tmp & 0xfe000000) != 0xfe000000 &&
(tmp & 0xfe000000) != 0) {
_rtld_error(
"%s: R_ARM_PC24 relocation @ %p to %s failed "
"(displacement %ld (%#lx) out of range)",
obj->path, where, defobj->strtab + def->st_name,
(long) tmp, (long) tmp);
return -1;
}
tmp >>= 2;
*where = (*where & 0xff000000) | (tmp & 0x00ffffff);
rdbg(dodebug, ("PC24 %s in %s --> %p @ %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, where, defobj->path));
break;
}
#endif /* __arm__ */
#ifdef __hppa__
case R_TYPE(DIR32):
if (ELF_R_SYM(rela->r_info)) {
/*
* This is either a DIR32 against a symbol
* (def->st_name != 0), or against a local
* section (def->st_name == 0).
*/
def = obj->symtab + ELF_R_SYM(rela->r_info);
defobj = obj;
if (def->st_name != 0)
/*
* While we're relocating self, _rtld_objlist
* is NULL, so we just pass in self.
*/
def = _rtld_find_symdef(rela->r_info, obj,
&defobj, false);
if (def == NULL)
return -1;
tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("DIR32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
} else {
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Addr _GOT_END_[];
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
/* This is the ...iffy hueristic. */
if (!dodebug ||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)_GOT_END_) {
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("DIR32 in %s --> %p", obj->path,
(void *)*where));
} else
rdbg(dodebug, ("DIR32 in %s stays at %p",
obj->path, (void *)*where));
}
break;
case R_TYPE(PLABEL32):
if (ELF_R_SYM(rela->r_info)) {
/*
* While we're relocating self, _rtld_objlist
* is NULL, so we just pass in self.
*/
def = _rtld_find_symdef(rela->r_info, obj, &defobj,
false);
if (def == NULL)
return -1;
tmp = _rtld_function_descriptor_alloc(defobj, def,
rela->r_addend);
if (tmp == (Elf_Addr)-1)
return -1;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PLABEL32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path));
} else {
/*
* This is a PLABEL for a static function, and the
* dynamic linker has both allocated a PLT entry
* for this function and told us where it is. We
* can safely use the PLT entry as the PLABEL
* because there should be no other PLABEL reloc
* referencing this function. This object should
* also have an IPLT relocation to initialize the
* PLT entry.
*
* The dynamic linker should also have ensured
* that the addend has the next-least-significant
* bit set; the $$dyncall millicode uses this to
* distinguish a PLABEL pointer from a plain
* function pointer.
*/
tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, ("PLABEL32 in %s --> %p",
obj->path, (void *)*where));
}
break;
#endif /* __hppa__ */
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(dodebug, ("COPY (avoid in main)"));
break;
default:
def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations\n",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
return 0;
}
#if !defined(__powerpc__) && !defined(__hppa__)
int