1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00
2005-03-28  Daniel Jacobowitz  <dan@codesourcery.com>
	[BZ #783]
	* elf/tst-auditmod1.c: Add MIPS support.
	* sysdeps/generic/ldsodefs.h (La_mips_32_regs): New.
	(La_mips_32_retval): New.
	(La_mips_64_regs): New.
	(La_mips_64_retval): New.
	(struct audit_ifaces): Add MIPS entries.
	* sysdeps/mips/dl-machine.h: Check RESOLVE_MAP instead of RESOLVE.
	(elf_machine_runtime_link_map, ELF_DL_FRAME_SIZE,
	ELF_DL_SAVE_ARG_REGS, ELF_DL_RESTORE_ARG_REGS,
	ELF_MACHINE_RUNTIME_TRAMPOLINE): Move to dl-trampoline.c.
	(RTLD_START): Align the stack before calling _dl_init_internal.
	Use .ent for _dl_start_user.
	(ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): Define.
	(elf_machine_rel, elf_machine_rel_relative, elf_machine_lazy_rel)
	(elf_machine_runtime_setup): Use "auto inline".
	(elf_machine_rela, elf_machine_rela_relative): Provide empty versions.
	(elf_machine_got_rel): Likewise.  Use RESOLVE_MAP.
	* sysdeps/mips/dl-trampoline.c: New file.
	* sysdeps/mips/bits/link.h: New file.
	* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
	(internal_syscall5): Use register operands instead of non-lvalue
	memory operands.
	(internal_syscall6): Likewise.
	(internal_syscall7): Likewise.
2005-03-28  Daniel Jacobowitz  <dan@codesourcery.com>

	[BZ #783]
	* elf/tst-auditmod1.c: Add MIPS support.
	* sysdeps/generic/ldsodefs.h (La_mips_32_regs): New.
	(La_mips_32_retval): New.
	(La_mips_64_regs): New.
	(La_mips_64_retval): New.
	(struct audit_ifaces): Add MIPS entries.
	* sysdeps/mips/dl-machine.h: Check RESOLVE_MAP instead of RESOLVE.
	(elf_machine_runtime_link_map, ELF_DL_FRAME_SIZE,
	ELF_DL_SAVE_ARG_REGS, ELF_DL_RESTORE_ARG_REGS,
	ELF_MACHINE_RUNTIME_TRAMPOLINE): Move to dl-trampoline.c.
	(RTLD_START): Align the stack before calling _dl_init_internal.
	Use .ent for _dl_start_user.
	(ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): Define.
	(elf_machine_rel, elf_machine_rel_relative, elf_machine_lazy_rel)
	(elf_machine_runtime_setup): Use "auto inline".
	(elf_machine_rela, elf_machine_rela_relative): Provide empty versions.
	(elf_machine_got_rel): Likewise.  Use RESOLVE_MAP.
	* sysdeps/mips/dl-trampoline.c: New file.
	* sysdeps/mips/bits/link.h: New file.
	* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
	(internal_syscall5): Use register operands instead of non-lvalue
	memory operands.
	(internal_syscall6): Likewise.
	(internal_syscall7): Likewise.
This commit is contained in:
Andreas Jaeger
2005-03-28 07:49:19 +00:00
parent 12403b3205
commit abc85e9fea
7 changed files with 534 additions and 279 deletions

View File

@@ -188,248 +188,6 @@ do { \
} while(0)
/* Get link map for callers object containing STUB_PC. */
static inline struct link_map *
elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
{
extern int _dl_mips_gnu_objects;
/* got[1] is reserved to keep its link map address for the shared
object generated by the gnu linker. If all are such objects, we
can find the link map from current GPREG simply. If not so, get
the link map for caller's object containing STUB_PC. */
if (_dl_mips_gnu_objects)
{
ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
ElfW(Word) g1;
g1 = ((ElfW(Word) *) got)[1];
if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
{
struct link_map *l =
(struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
ElfW(Addr) base, limit;
const ElfW(Phdr) *p = l->l_phdr;
ElfW(Half) this, nent = l->l_phnum;
/* For the common case of a stub being called from the containing
object, STUB_PC will point to somewhere within the object that
is described by the link map fetched via got[1]. Otherwise we
have to scan all maps. */
for (this = 0; this < nent; this++)
{
if (p[this].p_type == PT_LOAD)
{
base = p[this].p_vaddr + l->l_addr;
limit = base + p[this].p_memsz;
if (stub_pc >= base && stub_pc < limit)
return l;
}
}
}
}
struct link_map *l;
Lmid_t nsid;
for (nsid = 0; nsid < DL_NNS; ++nsid)
for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
{
ElfW(Addr) base, limit;
const ElfW(Phdr) *p = l->l_phdr;
ElfW(Half) this, nent = l->l_phnum;
for (this = 0; this < nent; ++this)
{
if (p[this].p_type == PT_LOAD)
{
base = p[this].p_vaddr + l->l_addr;
limit = base + p[this].p_memsz;
if (stub_pc >= base && stub_pc < limit)
return l;
}
}
}
_dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
return NULL;
}
#if _MIPS_SIM == _ABIO32
#define ELF_DL_FRAME_SIZE 40
#define ELF_DL_SAVE_ARG_REGS "\
sw $15, 36($29)\n \
sw $4, 16($29)\n \
sw $5, 20($29)\n \
sw $6, 24($29)\n \
sw $7, 28($29)\n \
"
#define ELF_DL_RESTORE_ARG_REGS "\
lw $31, 36($29)\n \
lw $4, 16($29)\n \
lw $5, 20($29)\n \
lw $6, 24($29)\n \
lw $7, 28($29)\n \
"
#define IFABIO32(X) X
#else /* _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 */
#define ELF_DL_FRAME_SIZE 80
#define ELF_DL_SAVE_ARG_REGS "\
sd $15, 72($29)\n \
sd $4, 8($29)\n \
sd $5, 16($29)\n \
sd $6, 24($29)\n \
sd $7, 32($29)\n \
sd $8, 40($29)\n \
sd $9, 48($29)\n \
sd $10, 56($29)\n \
sd $11, 64($29)\n \
"
#define ELF_DL_RESTORE_ARG_REGS "\
ld $31, 72($29)\n \
ld $4, 8($29)\n \
ld $5, 16($29)\n \
ld $6, 24($29)\n \
ld $7, 32($29)\n \
ld $8, 40($29)\n \
ld $9, 48($29)\n \
ld $10, 56($29)\n \
ld $11, 64($29)\n \
"
#define IFABIO32(X)
#endif
/* Define mips specific runtime resolver. The function __dl_runtime_resolve
is called from assembler function _dl_runtime_resolve which converts
special argument registers t7 ($15) and t8 ($24):
t7 address to return to the caller of the function
t8 index for this function symbol in .dynsym
to usual c arguments.
Other architectures call fixup from dl-runtime.c in
_dl_runtime_resolve. MIPS instead calls __dl_runtime_resolve. We
have to use our own version because of the way the got section is
treated on MIPS (we've also got ELF_MACHINE_PLT defined). */
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
/* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
generated by the gnu linker. */ \
int _dl_mips_gnu_objects = 1; \
\
/* This is called from assembly stubs below which the compiler can't see. */ \
static ElfW(Addr) \
__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr)) \
__attribute_used__; \
\
static ElfW(Addr) \
__dl_runtime_resolve (ElfW(Word) sym_index, \
ElfW(Word) return_address, \
ElfW(Addr) old_gpreg, \
ElfW(Addr) stub_pc) \
{ \
struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc); \
const ElfW(Sym) *const symtab \
= (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]); \
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); \
ElfW(Addr) *got \
= (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]); \
const ElfW(Word) local_gotno \
= (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
const ElfW(Word) gotsym \
= (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
const ElfW(Sym) *sym = &symtab[sym_index]; \
ElfW(Addr) value; \
\
/* FIXME: The symbol versioning stuff is not tested yet. */ \
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) \
{ \
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) \
{ \
default: \
{ \
const ElfW(Half) *vernum = \
(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); \
ElfW(Half) ndx = vernum[sym_index] & 0x7fff; \
const struct r_found_version *version = &l->l_versions[ndx]; \
\
if (version->hash != 0) \
{ \
value = _dl_lookup_symbol_x (strtab + sym->st_name, l, \
&sym, l->l_scope, version, \
ELF_RTYPE_CLASS_PLT, 0, 0); \
break; \
} \
/* Fall through. */ \
} \
case 0: \
value = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, \
l->l_scope, 0, ELF_RTYPE_CLASS_PLT, \
DL_LOOKUP_ADD_DEPENDENCY, 0); \
} \
\
/* Currently value contains the base load address of the object \
that defines sym. Now add in the symbol offset. */ \
value = (sym ? value + sym->st_value : 0); \
} \
else \
/* We already found the symbol. The module (and therefore its load \
address) is also known. */ \
value = l->l_addr + sym->st_value; \
\
/* Apply the relocation with that value. */ \
*(got + local_gotno + sym_index - gotsym) = value; \
\
return value; \
} \
\
asm ("\n \
.text\n \
.align 2\n \
.globl _dl_runtime_resolve\n \
.type _dl_runtime_resolve,@function\n \
.ent _dl_runtime_resolve\n \
_dl_runtime_resolve:\n \
.frame $29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n \
.set noreorder\n \
# Save GP.\n \
move $3, $28\n \
# Save arguments and sp value in stack.\n \
" STRINGXP(PTR_SUBIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n \
# Modify t9 ($25) so as to point .cpload instruction.\n \
" IFABIO32(STRINGXP(PTR_ADDIU) " $25, 12\n") " \
# Compute GP.\n \
" STRINGXP(SETUP_GP) "\n \
" STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n \
.set reorder\n \
# Save slot call pc.\n \
move $2, $31\n \
" IFABIO32(STRINGXP(CPRESTORE(32))) "\n \
" ELF_DL_SAVE_ARG_REGS " \
move $4, $24\n \
move $5, $15\n \
move $6, $3\n \
move $7, $2\n \
jal __dl_runtime_resolve\n \
" ELF_DL_RESTORE_ARG_REGS " \
" STRINGXP(RESTORE_GP64) "\n \
" STRINGXP(PTR_ADDIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n \
move $25, $2\n \
jr $25\n \
.end _dl_runtime_resolve\n \
.previous\n \
");
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
@@ -451,8 +209,8 @@ _dl_runtime_resolve:\n \
and not just plain _start. */
#define RTLD_START asm (\
".text\n"\
_RTLD_PROLOGUE(ENTRY_POINT) "\
".text\n\
" _RTLD_PROLOGUE(ENTRY_POINT) "\
" STRINGXV(SETUP_GPX($25)) "\n\
" STRINGXV(SETUP_GPX64($18,$25)) "\n\
# i386 ABI book says that the first entry of GOT holds\n\
@@ -475,10 +233,10 @@ _dl_runtime_resolve:\n \
" STRINGXP(PTR_ADDIU) " $29, 16\n\
# Get the value of label '_dl_start_user' in t9 ($25).\n\
" STRINGXP(PTR_LA) " $25, _dl_start_user\n\
.globl _dl_start_user\n\
.type _dl_start_user,@function\n\
.aent _dl_start_user\n\
_dl_start_user:\n\
" _RTLD_EPILOGUE(ENTRY_POINT) "\
\n\
\n\
" _RTLD_PROLOGUE(_dl_start_user) "\
" STRINGXP(SETUP_GP) "\n\
" STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
move $16, $28\n\
@@ -504,34 +262,48 @@ _dl_start_user:\n\
sll $7, $5, " STRINGXP (PTRLOG) "\n\
" STRINGXP(PTR_ADDU) " $7, $7, $6\n\
" STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
" STRINGXP(PTR_SUBIU) " $29, 32\n\
# Make sure the stack pointer is aligned for _dl_init_internal.\n\
and $2, $29, -2 * " STRINGXP(SZREG) "\n\
" STRINGXP(PTR_S) " $29, -4($2)\n\
" STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
" STRINGXP(SAVE_GP(16)) "\n\
# Call the function to run the initializers.\n\
jal _dl_init_internal\n\
" STRINGXP(PTR_ADDIU) " $29, 32\n\
# Restore the stack pointer for _start.\n\
" STRINGXP(PTR_L) " $29, 28($29)\n\
# Pass our finalizer function to the user in $2 as per ELF ABI.\n\
" STRINGXP(PTR_LA) " $2, _dl_fini\n\
# Jump to the user entry point.\n\
move $25, $17\n\
jr $25\n\t"\
_RTLD_EPILOGUE(ENTRY_POINT)\
_RTLD_EPILOGUE(_dl_start_user)\
".previous"\
);
/* The MIPS never uses Elfxx_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1
/* Names of the architecture-specific auditing callback functions. */
# if _MIPS_SIM == _ABIO32
# define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
# define ARCH_LA_PLTEXIT mips_o32_gnu_pltexit
# elif _MIPS_SIM == _ABIN32
# define ARCH_LA_PLTENTER mips_n32_gnu_pltenter
# define ARCH_LA_PLTEXIT mips_n32_gnu_pltexit
# else
# define ARCH_LA_PLTENTER mips_n64_gnu_pltenter
# define ARCH_LA_PLTEXIT mips_n64_gnu_pltexit
# endif
#endif /* !dl_machine_h */
#ifdef RESOLVE
#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
static inline void
#ifdef RTLD_BOOTSTRAP
__attribute__ ((always_inline))
#endif
auto inline void
__attribute__ ((always_inline))
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr)
@@ -635,23 +407,41 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
}
}
static inline void
auto inline void
__attribute__((always_inline))
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
void *const reloc_addr)
{
/* XXX Nothing to do. There is no relative relocation, right? */
}
static inline void
auto inline void
__attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map,
ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
{
/* Do nothing. */
}
auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
void *const reloc_addr)
{
}
auto inline void
__attribute__((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr)
{
}
#ifndef RTLD_BOOTSTRAP
/* Relocate GOT. */
static inline void
auto inline void
__attribute__((always_inline))
elf_machine_got_rel (struct link_map *map, int lazy)
{
ElfW(Addr) *got;
@@ -664,9 +454,9 @@ elf_machine_got_rel (struct link_map *map, int lazy)
const ElfW(Sym) *ref = sym; \
const struct r_found_version *version \
= vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL; \
ElfW(Addr) value; \
value = RESOLVE (&ref, version, R_MIPS_REL32); \
(ref)? value + ref->st_value: 0; \
struct link_map *sym_map; \
sym_map = RESOLVE_MAP (&ref, version, R_MIPS_REL32); \
ref ? sym_map->l_addr + ref->st_value : 0; \
})
if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
@@ -738,7 +528,8 @@ elf_machine_got_rel (struct link_map *map, int lazy)
/* Set up the loaded object described by L so its stub function
will jump to the on-demand fixup code __dl_runtime_resolve. */
static inline int
auto inline int
__attribute__((always_inline))
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
# ifndef RTLD_BOOTSTRAP
@@ -774,4 +565,4 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
#endif /* RESOLVE */
#endif /* RESOLVE_MAP */