initial commit
[glibc.git] / sysdeps / unix / bsd / bsd4.4 / kfreebsd / mips / dl-machine.h
1 /* Machine-dependent ELF dynamic relocation inline functions. MIPS version.
2 Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
6 Port to kFreeBSD (kernel of FreeBSD) by Robert Millan.
7
8 The GNU C Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 The GNU C Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with the GNU C Library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 02111-1307 USA. */
22
23 #include_next <dl-machine.h>
24
25 /* kFreeBSD puts arguments in a different location (see start.S). */
26 #undef RTLD_START
27 #define RTLD_START asm (\
28 ".text\n\
29 " _RTLD_PROLOGUE(ENTRY_POINT) "\
30 " STRINGXV(SETUP_GPX($25)) "\n\
31 " STRINGXV(SETUP_GPX64($18,$25)) "\n\
32 # i386 ABI book says that the first entry of GOT holds\n\
33 # the address of the dynamic structure. Though MIPS ABI\n\
34 # doesn't say nothing about this, I emulate this here.\n\
35 " STRINGXP(PTR_LA) " $9, _DYNAMIC\n\
36 # Subtract OFFSET_GP_GOT\n\
37 " STRINGXP(PTR_S) " $9, -0x7ff0($28)\n\
38 move $9, $29\n\
39 " STRINGXP(PTR_SUBIU) " $29, 16\n\
40 \n\
41 " STRINGXP(PTR_LA) " $8, .Lcoff\n\
42 bltzal $8, .Lcoff\n\
43 .Lcoff: " STRINGXP(PTR_SUBU) " $8, $31, $8\n\
44 \n\
45 " STRINGXP(PTR_LA) " $25, _dl_start\n\
46 " STRINGXP(PTR_ADDU) " $25, $8\n\
47 jalr $25\n\
48 \n\
49 " STRINGXP(PTR_ADDIU) " $29, 16\n\
50 # Get the value of label '_dl_start_user' in t9 ($25).\n\
51 " STRINGXP(PTR_LA) " $25, _dl_start_user\n\
52 " _RTLD_EPILOGUE(ENTRY_POINT) "\
53 \n\
54 \n\
55 " _RTLD_PROLOGUE(_dl_start_user) "\
56 " STRINGXP(SETUP_GP) "\n\
57 " STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
58 move $16, $28\n\
59 # Save the user entry point address in a saved register.\n\
60 move $17, $2\n\
61 # See if we were run as a command with the executable file\n\
62 # name as an extra leading argument.\n\
63 lw $2, _dl_skip_args\n\
64 beq $2, $0, 1f\n\
65 # Load the original argument count.\n\
66 " STRINGXP(PTR_L) " $10, 0($4)\n\
67 # Subtract _dl_skip_args from it.\n\
68 subu $10, $2\n\
69 # FIXME: unnecessary? Adjust the stack pointer to skip _dl_skip_args words.\n\
70 sll $2, " STRINGXP (PTRLOG) "\n\
71 " STRINGXP(PTR_ADDU) " $29, $2\n\
72 # Save back the modified argument count.\n\
73 " STRINGXP(PTR_S) " $10, 0($4)\n\
74 1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
75 " STRINGXP(PTR_L) /* or lw??? fixme */ " $5, 0($4)\n\
76 " STRINGXP(PTR_LA) " $6, " STRINGXP (PTRSIZE) "($4)\n\
77 " STRINGXP(PTR_L) " $4, _rtld_local\n\
78 sll $7, $5, " STRINGXP (PTRLOG) "\n\
79 " STRINGXP(PTR_ADDU) " $7, $7, $6\n\
80 " STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
81 # Make sure the stack pointer is aligned for _dl_init.\n\
82 and $2, $29, -2 * " STRINGXP(SZREG) "\n\
83 " STRINGXP(PTR_S) " $29, -" STRINGXP(SZREG) "($2)\n\
84 " STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
85 " STRINGXP(SAVE_GP(16)) "\n\
86 # Call the function to run the initializers.\n\
87 jal _dl_init\n\
88 # Restore the stack pointer for _start.\n\
89 " STRINGXP(PTR_L) " $29, 32-" STRINGXP(SZREG) "($29)\n\
90 # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
91 " STRINGXP(PTR_LA) " $2, _dl_fini\n\
92 # Jump to the user entry point.\n\
93 move $25, $17\n\
94 jr $25\n\t"\
95 _RTLD_EPILOGUE(_dl_start_user)\
96 ".previous"\
97 );