Document new tristate __libc_missing_32bit_uids.
[kopensolaris-gnu/glibc.git] / sysdeps / arm / dl-machine.h
index 49e9d08..78341fc 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  ARM version.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
 
 #include <sys/param.h>
 
-#include <assert.h>
+#define VALID_ELF_ABIVERSION(ver)      (ver == 0)
+#define VALID_ELF_OSABI(osabi) \
+  (osabi == ELFOSABI_SYSV || osabi == ELFOSABI_ARM)
+#define VALID_ELF_HEADER(hdr,exp,size) \
+  memcmp (hdr,exp,size-2) == 0 \
+  && VALID_ELF_OSABI (hdr[EI_OSABI]) \
+  && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
+
+#define CLEAR_CACHE(BEG,END)                                           \
+{                                                                      \
+  register unsigned long _beg __asm ("a1") = (unsigned long)(BEG);     \
+  register unsigned long _end __asm ("a2") = (unsigned long)(END);     \
+  register unsigned long _flg __asm ("a3") = 0;                                \
+  __asm __volatile ("swi 0x9f0002              @ sys_cacheflush"       \
+                   : /* no outputs */                                  \
+                   : /* no inputs */                                   \
+                   : "a1");                                            \
+}
 
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
 static inline int __attribute__ ((unused))
@@ -52,22 +69,14 @@ elf_machine_dynamic (void)
 
 
 /* Return the run-time load address of the shared object.  */
-// patb
 static inline Elf32_Addr __attribute__ ((unused))
 elf_machine_load_address (void)
 {
-  Elf32_Addr addr;
-  asm (" ldr ip,.L1
-       ldr r3,.L3
-       add r3, r3, sl
-       ldr ip,[sl, ip]
-       sub ip, r3, ip
-       b .L2
-       .L1: .word _dl_start(GOT)
-       .L3: .word _dl_start(GOTOFF)
-       .L2: mov %0, ip"
-       : "=r" (addr) : : "ip", "r3");
-  return addr;
+  extern void __dl_start asm ("_dl_start");
+  Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+  Elf32_Addr pcrel_addr;
+  asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
+  return pcrel_addr - got_addr;
 }
 
 
@@ -88,7 +97,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
         in.  Their initial contents will arrange when called to push an
         index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
         and then jump to _GLOBAL_OFFSET_TABLE[2].  */
-      got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
+      got = (Elf32_Addr *) l->l_info[DT_PLTGOT]->d_un.d_ptr;
       got[1] = (Elf32_Addr) l; /* Identify this shared object.  */
 
       /* The got[2] entry contains the address of a function which gets
@@ -99,8 +108,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
         end in this function.  */
       if (profile)
        {
-         //got[2] = (Elf32_Addr) &_dl_runtime_profile;
-         got[2] = (Elf32_Addr) &_dl_runtime_resolve;
+         got[2] = (Elf32_Addr) &_dl_runtime_profile;
          /* Say that we really want profiling and the timers are started.  */
          _dl_profile_map = l;
        }
@@ -283,9 +291,9 @@ _dl_start_user:
        str     r0, [sp]
 
        @ now we enter a _dl_init_next loop
-       ldr     r2, .L_DEF_SCOPE
-       ldr     r2, [sl, r2]
-       ldr     r4, [r2, #8]
+       ldr     r4, .L_MAIN_SEARCHLIST
+       ldr     r4, [sl, r4]
+       ldr     r4, [r4]
        @ call _dl_init_next to get the address of an initalizer
 0:     mov     r0, r4
        bl      _dl_init_next(PLT)
@@ -311,14 +319,14 @@ _dl_start_user:
        .word   _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4  \n\
 .L_SKIP_ARGS:                                  \n\
        .word   _dl_skip_args(GOTOFF)           \n\
-.L_DEF_SCOPE:                                  \n\
-       .word   _dl_default_scope(GOT)          \n\
 .L_STARTUP_FLAG:
        .word   _dl_starting_up(GOT)
 .L_FINI_PROC:
        .word   _dl_fini(GOT)
 .L_STACK_END:
        .word   __libc_stack_end(GOT)
+.L_MAIN_SEARCHLIST:
+       .word   _dl_main_searchlist(GOT)
 .previous\n\
 ");
 
@@ -345,10 +353,9 @@ extern const char *_dl_platform;
 static inline void __attribute__ ((unused))
 dl_platform_init (void)
 {
-  if (_dl_platform == NULL)
-    /* We default to ARM
-    This is where processors could be distinguished arm2, arm6, sa110, etc */
-    _dl_platform = "ARM";
+  if (_dl_platform != NULL && *_dl_platform == '\0')
+    /* Avoid an empty string which would disturb us.  */
+    _dl_platform = NULL;
 }
 
 static inline void
@@ -406,8 +413,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
            {
              const char *strtab;
 
-             strtab = ((const char *) map->l_addr
-                       + map->l_info[DT_STRTAB]->d_un.d_ptr);
+             strtab = (const void *) map->l_info[DT_STRTAB]->d_un.d_ptr;
              _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
                                ": Symbol `", strtab + refsym->st_name,
                                "' has different size in shared object, "
@@ -418,7 +424,13 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
          break;
        case R_ARM_GLOB_DAT:
        case R_ARM_JUMP_SLOT:
-         *reloc_addr = value;
+#ifdef RTLD_BOOTSTRAP
+         /* Fix weak undefined references.  */
+         if (sym != NULL && sym->st_value == 0)
+           *reloc_addr = 0;
+         else
+#endif
+           *reloc_addr = value;
          break;
        case R_ARM_ABS32:
          {
@@ -441,26 +453,40 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
            *reloc_addr += value;
            break;
          }
+       case R_ARM_PC24:
+         {
+            signed int addend;
+
+            addend = *reloc_addr & 0x00ffffff;
+            if (addend & 0x00800000) addend |= 0xff000000;
+
+            value = value - (unsigned int)reloc_addr + (addend << 2);
+            if (value & 0xfc000003)
+              _dl_signal_error (0, map->l_name,
+                         "R_ARM_PC24 relocation out of range");
+              
+            value = value >> 2;
+            value = (*reloc_addr & 0xff000000) | (value & 0x00ffffff);
+            *reloc_addr = value;
+         }
+       break;
        default:
-         assert (! "unexpected dynamic reloc type");
+         _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 0);
          break;
        }
     }
 }
 
 static inline void
-elf_machine_lazy_rel (Elf32_Addr l_addr, const Elf32_Rel *reloc)
+elf_machine_lazy_rel (struct link_map *map,
+                     Elf32_Addr l_addr, const Elf32_Rel *reloc)
 {
   Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
-  switch (ELF32_R_TYPE (reloc->r_info))
-    {
-    case R_ARM_JUMP_SLOT:
-      *reloc_addr += l_addr;
-      break;
-    default:
-      assert (! "unexpected PLT reloc type");
-      break;
-    }
+  /* Check for unexpected PLT reloc type.  */
+  if (ELF32_R_TYPE (reloc->r_info) == R_ARM_JUMP_SLOT)
+    *reloc_addr += l_addr;
+  else
+    _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
 }
 
 #endif /* RESOLVE */