mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-22 04:50:07 +00:00
[BZ #783]
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:
parent
12403b3205
commit
abc85e9fea
28
ChangeLog
28
ChangeLog
@ -1,3 +1,31 @@
|
||||
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-27 Andreas Jaeger <aj@suse.de>
|
||||
|
||||
* debug/warning-nop.c (__builtin___memcpy_chk): Define away to
|
||||
|
@ -162,6 +162,24 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
# define La_regs La_ia64_regs
|
||||
# define La_retval La_ia64_retval
|
||||
# define int_retval lrv_r8
|
||||
#elif defined __mips__ && _MIPS_SIM == _ABIO32
|
||||
# define pltenter la_mips_o32_gnu_pltenter
|
||||
# define pltexit la_mips_o32_gnu_pltexit
|
||||
# define La_regs La_mips_32_regs
|
||||
# define La_retval La_mips_32_retval
|
||||
# define int_retval lrv_v0
|
||||
#elif defined __mips__ && _MIPS_SIM == _ABIN32
|
||||
# define pltenter la_mips_n32_gnu_pltenter
|
||||
# define pltexit la_mips_n32_gnu_pltexit
|
||||
# define La_regs La_mips_64_regs
|
||||
# define La_retval La_mips_64_retval
|
||||
# define int_retval lrv_v0
|
||||
#elif defined __mips__ && _MIPS_SIM == _ABI64
|
||||
# define pltenter la_mips_n64_gnu_pltenter
|
||||
# define pltexit la_mips_n64_gnu_pltexit
|
||||
# define La_regs La_mips_64_regs
|
||||
# define La_retval La_mips_64_retval
|
||||
# define int_retval lrv_v0
|
||||
#else
|
||||
# error "architecture specific code needed"
|
||||
#endif
|
||||
|
@ -195,6 +195,10 @@ struct La_s390_64_regs;
|
||||
struct La_s390_64_retval;
|
||||
struct La_ia64_regs;
|
||||
struct La_ia64_retval;
|
||||
struct La_mips_32_regs;
|
||||
struct La_mips_32_retval;
|
||||
struct La_mips_64_regs;
|
||||
struct La_mips_64_retval;
|
||||
|
||||
struct audit_ifaces
|
||||
{
|
||||
@ -251,6 +255,21 @@ struct audit_ifaces
|
||||
uintptr_t *, struct La_ia64_regs *,
|
||||
unsigned int *, const char *name,
|
||||
long int *framesizep);
|
||||
Elf32_Addr (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_32_regs *,
|
||||
unsigned int *, const char *name,
|
||||
long int *framesizep);
|
||||
Elf32_Addr (*mips_n32_gnu_pltenter) (Elf32_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_64_regs *,
|
||||
unsigned int *, const char *name,
|
||||
long int *framesizep);
|
||||
Elf64_Addr (*mips_n64_gnu_pltenter) (Elf64_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_64_regs *,
|
||||
unsigned int *, const char *name,
|
||||
long int *framesizep);
|
||||
};
|
||||
union
|
||||
{
|
||||
@ -294,6 +313,21 @@ struct audit_ifaces
|
||||
uintptr_t *,
|
||||
const struct La_ia64_regs *,
|
||||
struct La_ia64_retval *, const char *);
|
||||
unsigned int (*mips_o32_gnu_pltexit) (Elf32_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_32_regs *,
|
||||
struct La_mips_32_retval *,
|
||||
const char *);
|
||||
unsigned int (*mips_n32_gnu_pltexit) (Elf32_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_64_regs *,
|
||||
struct La_mips_64_retval *,
|
||||
const char *);
|
||||
unsigned int (*mips_n64_gnu_pltexit) (Elf64_Sym *, unsigned int,
|
||||
uintptr_t *, uintptr_t *,
|
||||
const struct La_mips_64_regs *,
|
||||
struct La_mips_64_retval *,
|
||||
const char *);
|
||||
};
|
||||
unsigned int (*objclose) (uintptr_t *);
|
||||
|
||||
|
118
sysdeps/mips/bits/link.h
Normal file
118
sysdeps/mips/bits/link.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _LINK_H
|
||||
# error "Never include <bits/link.h> directly; use <link.h> instead."
|
||||
#endif
|
||||
|
||||
#include <sgidefs.h>
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
|
||||
/* Registers for entry into PLT on MIPS. */
|
||||
typedef struct La_mips_32_regs
|
||||
{
|
||||
uint32_t lr_reg[4]; /* $a0 through $a3 */
|
||||
double lr_fpreg[2]; /* $f12 and $f14 */
|
||||
uint32_t lr_ra;
|
||||
uint32_t lr_sp;
|
||||
} La_mips_32_regs;
|
||||
|
||||
/* Return values for calls from PLT on MIPS. */
|
||||
typedef struct La_mips_32_retval
|
||||
{
|
||||
uint32_t lrv_v0;
|
||||
uint32_t lrv_v1;
|
||||
double lrv_f0;
|
||||
double lrv_f2;
|
||||
} La_mips_32_retval;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct La_mips_64_regs
|
||||
{
|
||||
uint64_t lr_reg[8]; /* $a0 through $a7 */
|
||||
double lr_fpreg[8]; /* $f12 throgh $f19 */
|
||||
uint64_t lr_ra;
|
||||
uint64_t lr_sp;
|
||||
} La_mips_64_regs;
|
||||
|
||||
/* Return values for calls from PLT on MIPS. */
|
||||
typedef struct La_mips_64_retval
|
||||
{
|
||||
uint64_t lrv_v0;
|
||||
uint64_t lrv_v1;
|
||||
double lrv_f0;
|
||||
double lrv_f2;
|
||||
} La_mips_64_retval;
|
||||
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
|
||||
extern Elf32_Addr la_mips_o32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
La_mips_32_regs *__regs,
|
||||
unsigned int *__flags,
|
||||
const char *__symname,
|
||||
long int *__framesizep);
|
||||
extern unsigned int la_mips_o32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
const La_mips_32_regs *__inregs,
|
||||
La_mips_32_retval *__outregs,
|
||||
const char *symname);
|
||||
|
||||
#elif _MIPS_SIM == _ABIN32
|
||||
|
||||
extern Elf32_Addr la_mips_n32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
La_mips_64_regs *__regs,
|
||||
unsigned int *__flags,
|
||||
const char *__symname,
|
||||
long int *__framesizep);
|
||||
extern unsigned int la_mips_n32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
const La_mips_64_regs *__inregs,
|
||||
La_mips_64_retval *__outregs,
|
||||
const char *symname);
|
||||
|
||||
#else
|
||||
|
||||
extern Elf64_Addr la_mips_n64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
La_mips_64_regs *__regs,
|
||||
unsigned int *__flags,
|
||||
const char *__symname,
|
||||
long int *__framesizep);
|
||||
extern unsigned int la_mips_n64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
|
||||
uintptr_t *__refcook,
|
||||
uintptr_t *__defcook,
|
||||
const La_mips_64_regs *__inregs,
|
||||
La_mips_64_retval *__outregs,
|
||||
const char *symname);
|
||||
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
@ -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 */
|
||||
|
272
sysdeps/mips/dl-trampoline.c
Normal file
272
sysdeps/mips/dl-trampoline.c
Normal file
@ -0,0 +1,272 @@
|
||||
/* PLT trampoline. MIPS version.
|
||||
Copyright (C) 1996-2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* FIXME: Profiling of shared libraries is not implemented yet. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <link.h>
|
||||
#include <elf.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-machine.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
||||
/* The flag _dl_mips_gnu_objects is set if all dynamic objects are
|
||||
generated by the gnu linker. */
|
||||
int _dl_mips_gnu_objects = 1;
|
||||
|
||||
#define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
||||
|
||||
/* 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];
|
||||
struct link_map *sym_map;
|
||||
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)
|
||||
{
|
||||
sym_map = _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:
|
||||
sym_map = _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 ? sym_map->l_addr + 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;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
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\
|
||||
");
|
@ -194,16 +194,15 @@
|
||||
register long __a3 asm("$7") = (long) arg4; \
|
||||
__asm__ volatile ( \
|
||||
".set\tnoreorder\n\t" \
|
||||
"lw\t$2, %6\n\t" \
|
||||
"subu\t$29, 32\n\t" \
|
||||
"sw\t$2, 16($29)\n\t" \
|
||||
"sw\t%6, 16($29)\n\t" \
|
||||
"li\t$2, %5\t\t\t# " #name "\n\t" \
|
||||
"syscall\n\t" \
|
||||
"addiu\t$29, 32\n\t" \
|
||||
".set\treorder" \
|
||||
: "=r" (__v0), "+r" (__a3) \
|
||||
: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \
|
||||
"m" ((long)arg5) \
|
||||
"r" ((long)arg5) \
|
||||
: __SYSCALL_CLOBBERS); \
|
||||
err = __a3; \
|
||||
_sys_result = __v0; \
|
||||
@ -223,18 +222,16 @@
|
||||
register long __a3 asm("$7") = (long) arg4; \
|
||||
__asm__ volatile ( \
|
||||
".set\tnoreorder\n\t" \
|
||||
"lw\t$2, %6\n\t" \
|
||||
"lw\t$8, %7\n\t" \
|
||||
"subu\t$29, 32\n\t" \
|
||||
"sw\t$2, 16($29)\n\t" \
|
||||
"sw\t$8, 20($29)\n\t" \
|
||||
"sw\t%6, 16($29)\n\t" \
|
||||
"sw\t%7, 20($29)\n\t" \
|
||||
"li\t$2, %5\t\t\t# " #name "\n\t" \
|
||||
"syscall\n\t" \
|
||||
"addiu\t$29, 32\n\t" \
|
||||
".set\treorder" \
|
||||
: "=r" (__v0), "+r" (__a3) \
|
||||
: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \
|
||||
"m" ((long)arg5), "m" ((long)arg6) \
|
||||
"r" ((long)arg5), "r" ((long)arg6) \
|
||||
: __SYSCALL_CLOBBERS); \
|
||||
err = __a3; \
|
||||
_sys_result = __v0; \
|
||||
@ -254,20 +251,17 @@
|
||||
register long __a3 asm("$7") = (long) arg4; \
|
||||
__asm__ volatile ( \
|
||||
".set\tnoreorder\n\t" \
|
||||
"lw\t$2, %6\n\t" \
|
||||
"lw\t$8, %7\n\t" \
|
||||
"lw\t$9, %8\n\t" \
|
||||
"subu\t$29, 32\n\t" \
|
||||
"sw\t$2, 16($29)\n\t" \
|
||||
"sw\t$8, 20($29)\n\t" \
|
||||
"sw\t$9, 24($29)\n\t" \
|
||||
"sw\t%6, 16($29)\n\t" \
|
||||
"sw\t%7, 20($29)\n\t" \
|
||||
"sw\t%8, 24($29)\n\t" \
|
||||
"li\t$2, %5\t\t\t# " #name "\n\t" \
|
||||
"syscall\n\t" \
|
||||
"addiu\t$29, 32\n\t" \
|
||||
".set\treorder" \
|
||||
: "=r" (__v0), "+r" (__a3) \
|
||||
: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \
|
||||
"m" ((long)arg5), "m" ((long)arg6), "m" ((long)arg7) \
|
||||
"r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
|
||||
: __SYSCALL_CLOBBERS); \
|
||||
err = __a3; \
|
||||
_sys_result = __v0; \
|
||||
|
Loading…
Reference in New Issue
Block a user