Fix Wundef warning for ELF_MACHINE_NO_RELA
[platform/upstream/linaro-glibc.git] / sysdeps / mips / dl-machine.h
index 38470d1..eef0384 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  MIPS version.
-   Copyright (C) 1996-2012 Free Software Foundation, Inc.
+   Copyright (C) 1996-2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
 
@@ -14,9 +14,8 @@
    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.  */
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
 
 /*  FIXME: Profiling of shared libraries is not implemented yet.  */
 #ifndef dl_machine_h
@@ -61,6 +60,8 @@
    | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
 
 #define ELF_MACHINE_PLT_REL 1
+#define ELF_MACHINE_NO_REL 0
+#define ELF_MACHINE_NO_RELA 0
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -74,6 +75,16 @@ do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
        (ElfW(Addr)) (r); \
    } while (0)
 
+#if ((defined __mips_nan2008 && !defined HAVE_MIPS_NAN2008) \
+     || (!defined __mips_nan2008 && defined HAVE_MIPS_NAN2008))
+# error "Configuration inconsistency: __mips_nan2008 != HAVE_MIPS_NAN2008, overridden CFLAGS?"
+#endif
+#ifdef __mips_nan2008
+# define ELF_MACHINE_NAN2008 EF_MIPS_NAN2008
+#else
+# define ELF_MACHINE_NAN2008 0
+#endif
+
 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int __attribute_used__
 elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
@@ -84,6 +95,10 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
     return 0;
 #endif
 
+  /* Don't link 2008-NaN and legacy-NaN objects together.  */
+  if ((ehdr->e_flags & EF_MIPS_NAN2008) != ELF_MACHINE_NAN2008)
+    return 0;
+
   switch (ehdr->e_machine)
     {
     case EM_MIPS:
@@ -120,6 +135,7 @@ static inline ElfW(Addr)
 elf_machine_load_address (void)
 {
   ElfW(Addr) addr;
+#ifndef __mips16
   asm ("       .set noreorder\n"
        "       " STRINGXP (PTR_LA) " %0, 0f\n"
        "       bltzal $0, 0f\n"
@@ -129,6 +145,19 @@ elf_machine_load_address (void)
        :       "=r" (addr)
        :       /* No inputs */
        :       "$31");
+#else
+  ElfW(Addr) tmp;
+  asm ("       .set noreorder\n"
+       "       move %1,$gp\n"
+       "       lw %1,%%got(0f)(%1)\n"
+       "0:     .fill 0\n"              /* Clear the ISA bit on 0:.  */
+       "       la %0,0b\n"
+       "       addiu %1,%%lo(0b)\n"
+       "       subu %0,%1\n"
+       "       .set reorder\n"
+       :       "=d" (addr), "=d" (tmp)
+       :       /* No inputs */);
+#endif
   return addr;
 }
 
@@ -208,10 +237,11 @@ do {                                                                      \
       when it is called to store away the arguments passed
       to it.
 
-   2) That under Linux the entry is named __start
+   2) That under Unix the entry is named __start
       and not just plain _start.  */
 
-#define RTLD_START asm (\
+#ifndef __mips16
+# define RTLD_START asm (\
        ".text\n\
        " _RTLD_PROLOGUE(ENTRY_POINT) "\
        " STRINGXV(SETUP_GPX($25)) "\n\
@@ -267,13 +297,14 @@ do {                                                                      \
        " STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
        # Make sure the stack pointer is aligned for _dl_init_internal.\n\
        and $2, $29, -2 * " STRINGXP(SZREG) "\n\
-       " STRINGXP(PTR_S) " $29, -" STRINGXP(SZREG) "($2)\n\
+       move $8, $29\n\
        " STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
+       " STRINGXP(PTR_S) " $8, (32 - " STRINGXP(SZREG) ")($29)\n\
        " STRINGXP(SAVE_GP(16)) "\n\
        # Call the function to run the initializers.\n\
        jal _dl_init_internal\n\
        # Restore the stack pointer for _start.\n\
-       " STRINGXP(PTR_L)  " $29, 32-" STRINGXP(SZREG) "($29)\n\
+       " STRINGXP(PTR_L)  " $29, (32 - " STRINGXP(SZREG) ")($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\
@@ -283,6 +314,91 @@ do {                                                                       \
        ".previous"\
 );
 
+#else /* __mips16 */
+/* MIPS16 version.  We currently only support O32 under MIPS16; the proper
+   assembly preprocessor abstractions will need to be added if other ABIs
+   are to be supported.  */
+
+# define RTLD_START asm (\
+       ".text\n\
+       .set mips16\n\
+       " _RTLD_PROLOGUE (ENTRY_POINT) "\
+       # Construct GP value in $3.\n\
+       li $3, %hi(_gp_disp)\n\
+       addiu $4, $pc, %lo(_gp_disp)\n\
+       sll $3, 16\n\
+       addu $3, $4\n\
+       move $28, $3\n\
+       lw $4, %got(_DYNAMIC)($3)\n\
+       sw $4, -0x7ff0($3)\n\
+       move $4, $sp\n\
+       addiu $sp, -16\n\
+       # _dl_start() is sufficiently near to use pc-relative\n\
+       # load address.\n\
+       la $3, _dl_start\n\
+       move $25, $3\n\
+       jalr $3\n\
+       addiu $sp, 16\n\
+       " _RTLD_EPILOGUE (ENTRY_POINT) "\
+       \n\
+       \n\
+       " _RTLD_PROLOGUE (_dl_start_user) "\
+       li $16, %hi(_gp_disp)\n\
+       addiu $4, $pc, %lo(_gp_disp)\n\
+       sll $16, 16\n\
+       addu $16, $4\n\
+       move $17, $2\n\
+       move $28, $16\n\
+       lw $4, %got(_dl_skip_args)($16)\n\
+       lw $4, 0($4)\n\
+       beqz $4, 1f\n\
+       # Load the original argument count.\n\
+       lw $5, 0($sp)\n\
+       # Subtract _dl_skip_args from it.\n\
+       subu $5, $4\n\
+       # Adjust the stack pointer to skip _dl_skip_args words.\n\
+       sll $4, " STRINGXP (PTRLOG) "\n\
+       move $6, $sp\n\
+       addu $6, $4\n\
+       move $sp, $6\n\
+       # Save back the modified argument count.\n\
+       sw $5, 0($sp)\n\
+1:     # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
+       lw $4, %got(_rtld_local)($16)\n\
+       lw $4, 0($4)\n\
+       lw $5, 0($sp)\n\
+       addiu $6, $sp, " STRINGXP (PTRSIZE) "\n\
+       sll $7, $5, " STRINGXP (PTRLOG) "\n\
+       addu $7, $6\n\
+       addu $7, " STRINGXP (PTRSIZE) "\n\
+       # Make sure the stack pointer is aligned for _dl_init_internal.\n\
+       li $2, 2 * " STRINGXP (SZREG) "\n\
+       neg $2, $2\n\
+       move $3, $sp\n\
+       and $2, $3\n\
+       sw $3, -" STRINGXP (SZREG) "($2)\n\
+       addiu $2, -32\n\
+       move $sp, $2\n\
+       sw $16, 16($sp)\n\
+       # Call the function to run the initializers.\n\
+       lw $2, %call16(_dl_init_internal)($16)\n\
+       move $25, $2\n\
+       jalr $2\n\
+       # Restore the stack pointer for _start.\n\
+       lw $2, 32-" STRINGXP (SZREG) "($sp)\n\
+       move $sp, $2\n\
+       move $28, $16\n\
+       # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
+       lw $2, %call16(_dl_fini)($16)\n\
+       # Jump to the user entry point.\n\
+       move $25, $17\n\
+       jr $17\n\t"\
+       _RTLD_EPILOGUE (_dl_start_user)\
+       ".previous"\
+);
+
+#endif /* __mips16 */
+
 /* Names of the architecture-specific auditing callback functions.  */
 # if _MIPS_SIM == _ABIO32
 #  define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
@@ -325,6 +441,21 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
   return value;
 }
 
+/* The semantics of zero/non-zero values of undefined symbols differs
+   depending on whether the non-PIC ABI is in use.  Under the non-PIC
+   ABI, a non-zero value indicates that there is an address reference
+   to the symbol and thus it must always be resolved (except when
+   resolving a jump slot relocation) to the PLT entry whose address is
+   provided as the symbol's value; a zero value indicates that this
+   canonical-address behaviour is not required.  Yet under the classic
+   MIPS psABI, a zero value indicates that there is an address
+   reference to the function and the dynamic linker must resolve the
+   symbol immediately upon loading.  To avoid conflict, symbols for
+   which the dynamic linker must assume the non-PIC ABI semantics are
+   marked with the STO_MIPS_PLT flag.  */
+#define ELF_MACHINE_SYM_NO_MATCH(sym) \
+  ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
+
 #endif /* !dl_machine_h */
 
 #ifdef RESOLVE_MAP
@@ -535,8 +666,7 @@ elf_machine_reloc (struct link_map *map, ElfW(Addr) r_info,
            strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
            _dl_error_printf ("\
   %s: Symbol `%s' has different size in shared object, consider re-linking\n",
-                             rtld_progname ?: "<program name unknown>",
-                             strtab + refsym->st_name);
+                             RTLD_PROGNAME, strtab + refsym->st_name);
          }
        memcpy (reloc_addr, (void *) value,
                MIN (sym->st_size, refsym->st_size));
@@ -637,7 +767,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
 #define RESOLVE_GOTSYM(sym,vernum,sym_index,reloc)                       \
     ({                                                                   \
       const ElfW(Sym) *ref = sym;                                        \
-      const struct r_found_version *version                              \
+      const struct r_found_version *version __attribute__ ((unused))     \
        = vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL;   \
       struct link_map *sym_map;                                                  \
       sym_map = RESOLVE_MAP (&ref, version, reloc);                      \