Split _rtld_relocate_nonplt_object() into separate MD files.
This commit is contained in:
parent
b4a8cd2dbf
commit
00c3ad1f56
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue