Back to index

glibc  2.9
dl-machine.h
Go to the documentation of this file.
00001 /* Machine-dependent ELF dynamic relocation inline functions.  PA-RISC version.
00002    Copyright (C) 1995-1997,1999-2003
00003        Free Software Foundation, Inc.
00004    Contributed by David Huggins-Daines <dhd@debian.org>
00005    This file is part of the GNU C Library.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifndef dl_machine_h
00023 #define dl_machine_h 1
00024 
00025 #define ELF_MACHINE_NAME "hppa"
00026 
00027 #include <sys/param.h>
00028 #include <assert.h>
00029 #include <string.h>
00030 #include <link.h>
00031 #include <errno.h>
00032 #include <dl-fptr.h>
00033 #include <abort-instr.h>
00034 #include <tls.h>
00035 
00036 # define VALID_ELF_OSABI(osabi)           ((osabi == ELFOSABI_SYSV) || (osabi == ELFOSABI_LINUX))
00037 # define VALID_ELF_ABIVERSION(ver) (ver == 0)
00038 # define VALID_ELF_HEADER(hdr,exp,size) \
00039   memcmp (hdr,exp,size-2) == 0 \
00040   && VALID_ELF_OSABI (hdr[EI_OSABI]) \
00041   && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
00042 
00043 /* These two definitions must match the definition of the stub in 
00044    bfd/elf32-hppa.c (see plt_stub[]).
00045    
00046    a. Define the size of the *entire* stub we place at the end of the PLT
00047    table (right up against the GOT).
00048    
00049    b. Define the number of bytes back from the GOT to the entry point of
00050    the PLT stub. You see the PLT stub must be entered in the middle
00051    so it can depwi to find it's own address (long jump stub) 
00052    
00053    c. Define the size of a single PLT entry so we can jump over the
00054    last entry to get the stub address */
00055        
00056 #define SIZEOF_PLT_STUB (7*4)
00057 #define GOT_FROM_PLT_STUB (4*4)
00058 #define PLT_ENTRY_SIZE (2*4)
00059 
00060 /* Initialize the function descriptor table before relocations */
00061 static inline void
00062 __hppa_init_bootstrap_fdesc_table (struct link_map *map)
00063 {
00064   ElfW(Addr) *boot_table;
00065 
00066   /* Careful: this will be called before got has been relocated... */
00067   ELF_MACHINE_LOAD_ADDRESS(boot_table,_dl_boot_fptr_table);
00068 
00069   map->l_mach.fptr_table_len = ELF_MACHINE_BOOT_FPTR_TABLE_LEN;
00070   map->l_mach.fptr_table = boot_table;
00071 }
00072 
00073 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info)            \
00074        __hppa_init_bootstrap_fdesc_table (&bootstrap_map);
00075 
00076 /* Return nonzero iff ELF header is compatible with the running host.  */
00077 static inline int
00078 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
00079 {
00080   return ehdr->e_machine == EM_PARISC;
00081 }
00082 
00083 /* Return the link-time address of _DYNAMIC.  */
00084 static inline Elf32_Addr
00085 elf_machine_dynamic (void) __attribute__ ((const));
00086 
00087 static inline Elf32_Addr
00088 elf_machine_dynamic (void)
00089 {
00090   Elf32_Addr dynamic;
00091 
00092   asm ("b,l   1f,%0\n"
00093 "      depi   0,31,2,%0\n"
00094 "1:    addil  L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8),%0\n"
00095 "      ldw    R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%%r1),%0\n"
00096        : "=r" (dynamic) : : "r1");
00097 
00098   return dynamic;
00099 }
00100 
00101 /* Return the run-time load address of the shared object.  */
00102 static inline Elf32_Addr
00103 elf_machine_load_address (void) __attribute__ ((const));
00104 
00105 static inline Elf32_Addr
00106 elf_machine_load_address (void)
00107 {
00108   Elf32_Addr dynamic;
00109 
00110   asm (
00111 "      b,l    1f,%0\n"
00112 "      depi   0,31,2,%0\n"
00113 "1:    addil  L'_DYNAMIC - ($PIC_pcrel$0 - 8),%0\n"
00114 "      ldo    R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%%r1),%0\n"
00115    : "=r" (dynamic) : : "r1");
00116 
00117   return dynamic - elf_machine_dynamic ();
00118 }
00119 
00120 /* Fixup a PLT entry to bounce directly to the function at VALUE. */ 
00121 static inline struct fdesc __attribute__ ((always_inline)) 
00122 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
00123                      const Elf32_Rela *reloc,
00124                      Elf32_Addr *reloc_addr, struct fdesc value)
00125 {
00126   volatile Elf32_Addr *rfdesc = reloc_addr;
00127   /* map is the link_map for the caller, t is the link_map for the object
00128      being called */
00129   rfdesc[1] = value.gp;
00130   /* Need to ensure that the gp is visible before the code
00131      entry point is updated */
00132   rfdesc[0] = value.ip;
00133   return value;
00134 }
00135 
00136 /* Return the final value of a plt relocation.  */
00137 static inline struct fdesc 
00138 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
00139                      struct fdesc value)
00140 {
00141   /* We are rela only, return a function descriptor as a plt entry. */
00142   return (struct fdesc) { value.ip + reloc->r_addend, value.gp };
00143 }
00144 
00145 /* Set up the loaded object described by L so its unrelocated PLT
00146    entries will jump to the on-demand fixup code in dl-runtime.c.  */
00147 
00148 static inline int
00149 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
00150 {
00151   Elf32_Addr *got = NULL;
00152   Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type, r_sym;
00153   const Elf32_Rela *reloc;
00154   struct fdesc *fptr;
00155   static union {
00156     unsigned char c[8];
00157     Elf32_Addr i[2];
00158   } sig = {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}};
00159               
00160   /* If we don't have a PLT we can just skip all this... */
00161   if (__builtin_expect (l->l_info[DT_JMPREL] == NULL,0))
00162     return lazy;
00163   
00164   /* All paths use these values */ 
00165   l_addr = l->l_addr;
00166   jmprel = D_PTR(l, l_info[DT_JMPREL]);
00167   end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val;
00168   
00169   extern void _dl_runtime_resolve (void);
00170   extern void _dl_runtime_profile (void);
00171  
00172   /* Linking lazily */
00173   if (lazy)
00174     {
00175       /* FIXME: Search for the got, but backwards through the relocs, technically we should
00176          find it on the first try. However, assuming the relocs got out of order the 
00177          routine is made a bit more robust by searching them all in case of failure. */
00178       for (iplt = (end_jmprel - sizeof(Elf32_Rela)); iplt >= jmprel; iplt -= sizeof (Elf32_Rela))
00179         {
00180              
00181          reloc = (const Elf32_Rela *) iplt;
00182           r_type = ELF32_R_TYPE (reloc->r_info);
00183           r_sym = ELF32_R_SYM (reloc->r_info);
00184 
00185           got = (Elf32_Addr *) (reloc->r_offset + l_addr + PLT_ENTRY_SIZE + SIZEOF_PLT_STUB);
00186 
00187           /* If we aren't an IPLT, and we aren't NONE then it's a bad reloc */
00188           if (__builtin_expect (r_type != R_PARISC_IPLT, 0))
00189            {
00190              if (__builtin_expect (r_type != R_PARISC_NONE, 0))
00191                _dl_reloc_bad_type (l, r_type, 1);
00192              continue;
00193            }
00194        
00195           /* Check for the plt_stub that binutils placed here for us 
00196              to use with _dl_runtime_resolve  */
00197           if (got[-2] != sig.i[0] || got[-1] != sig.i[1])
00198             {
00199               got = NULL; /* Not the stub... keep looking */
00200             } 
00201           else 
00202            {
00203               /* Found the GOT! */        
00204               register Elf32_Addr ltp __asm__ ("%r19");
00205               
00206               /* Identify this shared object. Second entry in the got. */
00207               got[1] = (Elf32_Addr) l;
00208               
00209               /* This function will be called to perform the relocation. */
00210               if (__builtin_expect (!profile, 1))
00211                 {
00212                   /* If a static application called us, then _dl_runtime_resolve is not
00213                    a function descriptor, but the *real* address of the function... */
00214                 if((unsigned long) &_dl_runtime_resolve & 3)
00215                   {
00216                       got[-2] = (Elf32_Addr) ((struct fdesc *) 
00217                                   ((unsigned long) &_dl_runtime_resolve & ~3))->ip;
00218                   }
00219                 else
00220                   {
00221                     /* Static executable! */
00222                       got[-2] = (Elf32_Addr) &_dl_runtime_resolve;
00223                   }
00224                 }
00225               else
00226                {
00227                  if (GLRO(dl_profile) != NULL
00228                     && _dl_name_match_p (GLRO(dl_profile), l))
00229                    {
00230                     /* This is the object we are looking for.  Say that
00231                        we really want profiling and the timers are
00232                        started.  */
00233                       GL(dl_profile_map) = l;
00234                     }
00235 
00236                 if((unsigned long) &_dl_runtime_resolve & 3)
00237                   {
00238                       got[-2] = (Elf32_Addr) ((struct fdesc *)
00239                                   ((unsigned long) &_dl_runtime_profile & ~3))->ip;
00240                   }
00241                 else
00242                   {
00243                     /* Static executable */
00244                       got[-2] = (Elf32_Addr) &_dl_runtime_profile;
00245                   }
00246                 }
00247               /* Plunk in the gp of this function descriptor so we 
00248                 can make the call to _dl_runtime_xxxxxx */
00249               got[-1] = ltp;
00250               break;
00251               /* Done looking for the GOT, and stub is setup */
00252             } /* else we found the GOT */
00253         } /* for, walk the relocs backwards */
00254 
00255       if(!got) 
00256         return 0; /* No lazy linking for you! */
00257   
00258       /* Process all the relocs, now that we know the GOT... */    
00259       for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
00260        {
00261          reloc = (const Elf32_Rela *) iplt;
00262          r_type = ELF32_R_TYPE (reloc->r_info);
00263          r_sym = ELF32_R_SYM (reloc->r_info);
00264 
00265          if (__builtin_expect (r_type == R_PARISC_IPLT, 1))
00266            {
00267              fptr = (struct fdesc *) (reloc->r_offset + l_addr);
00268              if (r_sym != 0)
00269               {
00270                 /* Relocate the pointer to the stub.  */
00271                 fptr->ip = (Elf32_Addr) got - GOT_FROM_PLT_STUB;
00272 
00273                 /* Instead of the LTP value, we put the reloc offset
00274                    here.  The trampoline code will load the proper
00275                    LTP and pass the reloc offset to the fixup
00276                    function.  */
00277                 fptr->gp = iplt - jmprel;
00278               } /* r_sym != 0 */
00279              else
00280               {
00281                 /* Relocate this *ABS* entry.  */
00282                 fptr->ip = reloc->r_addend + l_addr;
00283                 fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
00284               }
00285            } /* r_type == R_PARISC_IPLT */
00286        } /* for all the relocations */ 
00287     } /* if lazy */
00288   else
00289     {
00290       for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
00291         {
00292           reloc = (const Elf32_Rela *) iplt;
00293           r_type = ELF32_R_TYPE (reloc->r_info);
00294           r_sym = ELF32_R_SYM (reloc->r_info);
00295 
00296           if (__builtin_expect ((r_type == R_PARISC_IPLT) && (r_sym == 0), 1))
00297             {
00298               fptr = (struct fdesc *) (reloc->r_offset + l_addr);
00299               /* Relocate this *ABS* entry, set only the gp, the rest is set later
00300                  when elf_machine_rela_relative is called (WITHOUT the linkmap)  */
00301               fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
00302             } /* r_type == R_PARISC_IPLT */
00303         } /* for all the relocations */ 
00304     }    
00305   return lazy;
00306 }
00307 
00308 
00309 /* Names of the architecture-specific auditing callback functions.  */
00310 #define ARCH_LA_PLTENTER hppa_gnu_pltenter
00311 #define ARCH_LA_PLTEXIT hppa_gnu_pltexit
00312 
00313 /* Initial entry point code for the dynamic linker.
00314    The C function `_dl_start' is the real entry point;
00315    its return value is the user program's entry point.  */
00316 
00317 #define RTLD_START \
00318 /* Set up dp for any non-PIC lib constructors that may be called.  */ \
00319 static struct link_map * __attribute__((used))                        \
00320 set_dp (struct link_map *map)                                         \
00321 {                                                              \
00322   register Elf32_Addr dp asm ("%r27");                                \
00323   dp = D_PTR (map, l_info[DT_PLTGOT]);                                \
00324   asm volatile ("" : : "r" (dp));                              \
00325   return map;                                                  \
00326 }                                                              \
00327                                                                \
00328 asm (                                                          \
00329 "      .text\n"                                                \
00330 "      .globl _start\n"                                        \
00331 "      .type _start,@function\n"                               \
00332 "_start:\n"                                                    \
00333        /* The kernel does not give us an initial stack frame. */      \
00334 "      ldo    64(%sp),%sp\n"                                          \
00335        /* Save the relevant arguments (yes, those are the correct     \
00336           registers, the kernel is weird) in their stack slots. */    \
00337 "      stw    %r25,-40(%sp)\n" /* argc */                      \
00338 "      stw    %r24,-44(%sp)\n" /* argv */                      \
00339                                                                \
00340        /* We need the LTP, and we need it now.                        \
00341           $PIC_pcrel$0 points 8 bytes past the current instruction,   \
00342           just like a branch reloc.  This sequence gets us the        \
00343           runtime address of _DYNAMIC. */                      \
00344 "      bl     0f,%r19\n"                                       \
00345 "      depi   0,31,2,%r19\n"       /* clear priviledge bits */        \
00346 "0:    addil  L'_DYNAMIC - ($PIC_pcrel$0 - 8),%r19\n"                 \
00347 "      ldo    R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%r26\n"           \
00348                                                                \
00349        /* The link time address is stored in the first entry of the   \
00350           GOT.  */                                             \
00351 "      addil  L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16),%r19\n"   \
00352 "      ldw    R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r20\n" \
00353                                                                \
00354 "      sub    %r26,%r20,%r20\n"    /* Calculate load offset */ \
00355                                                                \
00356        /* Rummage through the dynamic entries, looking for            \
00357           DT_PLTGOT.  */                                       \
00358 "      ldw,ma 8(%r26),%r19\n"                                         \
00359 "1:    cmpib,=,n 3,%r19,2f\n"      /* tag == DT_PLTGOT? */                   \
00360 "      cmpib,<>,n 0,%r19,1b\n"                                        \
00361 "      ldw,ma 8(%r26),%r19\n"                                         \
00362                                                                \
00363        /* Uh oh!  We didn't find one.  Abort. */               \
00364 "      iitlbp %r0,(%sr0,%r0)\n"                                \
00365                                                                \
00366 "2:    ldw    -4(%r26),%r19\n"     /* Found it, load value. */ \
00367 "      add    %r19,%r20,%r19\n"    /* And add the load offset. */     \
00368                                                                \
00369        /* Our initial stack layout is rather different from everyone  \
00370           else's due to the unique PA-RISC ABI.  As far as I know it  \
00371           looks like this:                                     \
00372                                                                \
00373           -----------------------------------  (this frame created above) \
00374           |         32 bytes of magic       |                         \
00375           |---------------------------------|                         \
00376           | 32 bytes argument/sp save area  |                         \
00377           |---------------------------------|  ((current->mm->env_end)       \
00378           |         N bytes of slack        |     + 63 & ~63)         \
00379           |---------------------------------|                         \
00380           |      envvar and arg strings     |                         \
00381           |---------------------------------|                         \
00382           |       ELF auxiliary info           |                      \
00383           |         (up to 28 words)        |                         \
00384           |---------------------------------|                         \
00385           |  Environment variable pointers  |                         \
00386           |         upwards to NULL            |                      \
00387           |---------------------------------|                         \
00388           |        Argument pointers        |                         \
00389           |         upwards to NULL            |                      \
00390           |---------------------------------|                         \
00391           |          argc (1 word)          |                         \
00392           -----------------------------------                         \
00393                                                                \
00394          So, obviously, we can't just pass %sp to _dl_start.  That's  \
00395          okay, argv-4 will do just fine.                       \
00396                                                                \
00397          The pleasant part of this is that if we need to skip         \
00398          arguments we can just decrement argc and move argv, because  \
00399          the stack pointer is utterly unrelated to the location of    \
00400          the environment and argument vectors. */                     \
00401                                                                \
00402        /* This is always within range so we'll be okay. */            \
00403 "      bl     _dl_start,%rp\n"                                 \
00404 "      ldo    -4(%r24),%r26\n"                                 \
00405                                                                \
00406 "      .globl _dl_start_user\n"                                \
00407 "      .type _dl_start_user,@function\n"                       \
00408 "_dl_start_user:\n"                                            \
00409        /* Save the entry point in %r3. */                      \
00410 "      copy   %ret0,%r3\n"                                     \
00411                                                                \
00412        /* Remember the lowest stack address. */                \
00413 "      addil  LT'__libc_stack_end,%r19\n"                      \
00414 "      ldw    RT'__libc_stack_end(%r1),%r20\n"                 \
00415 "      stw    %sp,0(%r20)\n"                                          \
00416                                                                \
00417        /* See if we were called as a command with the executable file \
00418           name as an extra leading argument. */                \
00419 "      addil  LT'_dl_skip_args,%r19\n"                         \
00420 "      ldw    RT'_dl_skip_args(%r1),%r20\n"                           \
00421 "      ldw    0(%r20),%r20\n"                                         \
00422                                                                \
00423 "      ldw    -40(%sp),%r25\n"     /* argc */                  \
00424 "      comib,=       0,%r20,.Lnofix\n"    /* FIXME: Mispredicted branch */\
00425 "      ldw    -44(%sp),%r24\n"     /* argv (delay slot) */            \
00426                                                                \
00427 "      sub    %r25,%r20,%r25\n"                                \
00428 "      stw    %r25,-40(%sp)\n"                                 \
00429 "      sh2add %r20,%r24,%r24\n"                                \
00430 "      stw    %r24,-44(%sp)\n"                                 \
00431                                                                \
00432 ".Lnofix:\n"                                                   \
00433 "      addil  LT'_rtld_local,%r19\n"                                  \
00434 "      ldw    RT'_rtld_local(%r1),%r26\n"                      \
00435 "      bl     set_dp, %r2\n"                                          \
00436 "      ldw    0(%r26),%r26\n"                                         \
00437                                                                \
00438        /* Call _dl_init(_dl_loaded, argc, argv, envp). */             \
00439 "      copy   %r28,%r26\n"                                     \
00440                                                                \
00441        /* envp = argv + argc + 1 */                                   \
00442 "      sh2add %r25,%r24,%r23\n"                                \
00443 "      bl     _dl_init_internal,%r2\n"                         \
00444 "      ldo    4(%r23),%r23\n"      /* delay slot */                   \
00445                                                                \
00446        /* Reload argc, argv to the registers start.S expects.  */     \
00447 "      ldw    -40(%sp),%r25\n"                                 \
00448 "      ldw    -44(%sp),%r24\n"                                 \
00449                                                                \
00450        /* _dl_fini is a local function in the loader, so we construct \
00451            a false OPD here and pass this to the application.  */     \
00452        /* FIXME: Should be able to use P%, and LR RR to have the      \
00453           the linker construct a proper OPD.  */               \
00454 "      .section .data\n"                                       \
00455 "__dl_fini_plabel:\n"                                                 \
00456 "      .word  _dl_fini\n"                                      \
00457 "      .word  0xdeadbeef\n"                                    \
00458 "      .previous\n"                                            \
00459                                                                \
00460        /* %r3 contains a function pointer, we need to mask out the    \
00461           lower bits and load the gp and jump address. */             \
00462 "      depi   0,31,2,%r3\n"                                    \
00463 "      ldw    0(%r3),%r2\n"                                    \
00464 "      addil  LT'__dl_fini_plabel,%r19\n"                      \
00465 "      ldw    RT'__dl_fini_plabel(%r1),%r23\n"                 \
00466 "      stw    %r19,4(%r23)\n"                                         \
00467 "      ldw    4(%r3),%r19\n"       /* load the object's gp */         \
00468 "      bv     %r0(%r2)\n"                                      \
00469 "      depi   2,31,2,%r23\n"       /* delay slot */                   \
00470 );
00471 
00472 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or 
00473    a TLS variable, so references should not be allowed to define the value.
00474    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
00475    of the main executable's symbols, as for a COPY reloc.  */
00476 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
00477 # define elf_machine_type_class(type)                          \
00478   ((((type) == R_PARISC_IPLT                                   \
00479   || (type) == R_PARISC_EPLT                                   \
00480   || (type) == R_PARISC_TLS_DTPMOD32                           \
00481   || (type) == R_PARISC_TLS_DTPOFF32                           \
00482   || (type) == R_PARISC_TLS_TPREL32)                           \
00483   * ELF_RTYPE_CLASS_PLT)                                \
00484   | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
00485 #else
00486 #define elf_machine_type_class(type)                           \
00487  ((((type) == R_PARISC_IPLT                             \
00488    || (type) == R_PARISC_EPLT)                                 \
00489    * ELF_RTYPE_CLASS_PLT)                               \
00490    | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
00491 #endif
00492 
00493 /* Used by the runtime in fixup to figure out if reloc is *really* PLT */
00494 #define ELF_MACHINE_JMP_SLOT R_PARISC_IPLT
00495 #define ELF_MACHINE_SIZEOF_JMP_SLOT PLT_ENTRY_SIZE
00496 
00497 /* We only use RELA. */
00498 #define ELF_MACHINE_NO_REL 1
00499 
00500 /* Return the address of the entry point. */
00501 #define ELF_MACHINE_START_ADDRESS(map, start) \
00502   DL_STATIC_FUNCTION_ADDRESS (map, start)
00503 
00504 /* We define an initialization functions.  This is called very early in
00505  *    _dl_sysdep_start.  */
00506 #define DL_PLATFORM_INIT dl_platform_init ()
00507 
00508 static inline void __attribute__ ((unused))
00509 dl_platform_init (void)
00510 {
00511        if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
00512        /* Avoid an empty string which would disturb us.  */
00513               GLRO(dl_platform) = NULL;
00514 }
00515        
00516 #endif /* !dl_machine_h */
00517 
00518 /* These are only actually used where RESOLVE_MAP is defined, anyway. */
00519 #ifdef RESOLVE_MAP
00520 
00521 #define reassemble_21(as21) \
00522   (  (((as21) & 0x100000) >> 20) \
00523    | (((as21) & 0x0ffe00) >> 8) \
00524    | (((as21) & 0x000180) << 7) \
00525    | (((as21) & 0x00007c) << 14) \
00526    | (((as21) & 0x000003) << 12))
00527 
00528 #define reassemble_14(as14) \
00529   (  (((as14) & 0x1fff) << 1) \
00530    | (((as14) & 0x2000) >> 13))
00531 
00532 auto void __attribute__((always_inline))
00533 elf_machine_rela (struct link_map *map, 
00534                 const Elf32_Rela *reloc,
00535                 const Elf32_Sym *sym, 
00536                 const struct r_found_version *version,
00537                 void *const reloc_addr_arg)
00538 {
00539   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00540   const Elf32_Sym *const refsym = sym;
00541   unsigned long const r_type = ELF32_R_TYPE (reloc->r_info);
00542   struct link_map *sym_map;
00543   Elf32_Addr value;
00544 
00545 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC && !defined SHARED
00546   /* This is defined in rtld.c, but nowhere in the static libc.a; make the
00547      reference weak so static programs can still link.  This declaration
00548      cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
00549      because rtld.c contains the common defn for _dl_rtld_map, which is
00550      incompatible with a weak decl in the same file.  */
00551   weak_extern (GL(dl_rtld_map));
00552 # endif
00553 
00554   /* RESOLVE_MAP will return a null value for undefined syms, and
00555      non-null for all other syms.  In particular, relocs with no
00556      symbol (symbol index of zero), also called *ABS* relocs, will be
00557      resolved to MAP.  (The first entry in a symbol table is all
00558      zeros, and an all zero Elf32_Sym has a binding of STB_LOCAL.)
00559      See RESOLVE_MAP definition in elf/dl-reloc.c  */
00560 # ifdef RTLD_BOOTSTRAP
00561   /* RESOLVE_MAP in rtld.c doesn't have the local sym test.  */
00562   sym_map = (ELF32_ST_BIND (sym->st_info) != STB_LOCAL
00563             ? RESOLVE_MAP (&sym, version, r_type) : map);
00564 # else
00565   sym_map = RESOLVE_MAP (&sym, version, r_type);
00566 # endif
00567   
00568   if (sym_map)
00569     {
00570       value = sym ? sym_map->l_addr + sym->st_value : 0;
00571       value += reloc->r_addend;
00572     }
00573   else
00574     value = 0;
00575 
00576   switch (r_type)
00577     {
00578     case R_PARISC_DIR32:
00579       /* .eh_frame can have unaligned relocs.  */
00580       if ((unsigned long) reloc_addr_arg & 3)
00581        {
00582          char *rel_addr = (char *) reloc_addr_arg;
00583          rel_addr[0] = value >> 24;
00584          rel_addr[1] = value >> 16;
00585          rel_addr[2] = value >> 8;
00586          rel_addr[3] = value;
00587          return;
00588        }
00589       break;
00590 
00591     case R_PARISC_DIR21L:
00592       {
00593        unsigned int insn = *(unsigned int *)reloc_addr;
00594         value = sym_map->l_addr + sym->st_value 
00595               + ((reloc->r_addend + 0x1000) & -0x2000);
00596        value = value >> 11;
00597        insn = (insn &~ 0x1fffff) | reassemble_21 (value);
00598        *(unsigned int *)reloc_addr = insn;
00599       }
00600       return;
00601 
00602     case R_PARISC_DIR14R:
00603       {
00604        unsigned int insn = *(unsigned int *)reloc_addr;
00605        value = ((sym_map->l_addr + sym->st_value) & 0x7ff) 
00606               + (((reloc->r_addend & 0x1fff) ^ 0x1000) - 0x1000);
00607        insn = (insn &~ 0x3fff) | reassemble_14 (value);
00608        *(unsigned int *)reloc_addr = insn;
00609       }
00610       return;
00611 
00612     case R_PARISC_PLABEL32:
00613       /* Easy rule: If there is a symbol and it is global, then we
00614          need to make a dynamic function descriptor.  Otherwise we
00615          have the address of a PLT slot for a local symbol which we
00616          know to be unique. */
00617       if (sym == NULL
00618          || sym_map == NULL
00619          || ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
00620         {
00621          break;
00622         }
00623       /* Set bit 30 to indicate to $$dyncall that this is a PLABEL.
00624          We have to do this outside of the generic function descriptor
00625         code, since it doesn't know about our requirement for setting
00626         protection bits */
00627       value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
00628       break;
00629 
00630     case R_PARISC_PLABEL21L:
00631     case R_PARISC_PLABEL14R:
00632       {
00633        unsigned int insn = *(unsigned int *)reloc_addr;
00634 
00635         if (__builtin_expect (sym == NULL, 0))
00636           break;
00637 
00638         value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
00639 
00640         if (r_type == R_PARISC_PLABEL21L)
00641          {
00642            value >>= 11;
00643            insn = (insn &~ 0x1fffff) | reassemble_21 (value);
00644          }
00645         else
00646          {
00647            value &= 0x7ff;
00648            insn = (insn &~ 0x3fff) | reassemble_14 (value);
00649          }
00650 
00651        *(unsigned int *)reloc_addr = insn;
00652       }
00653       return;
00654 
00655     case R_PARISC_IPLT:
00656       if (__builtin_expect (sym_map != NULL, 1))
00657         {
00658          elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, 
00659                              DL_FIXUP_MAKE_VALUE(sym_map, value));
00660         } 
00661       else 
00662         {
00663          /* If we get here, it's a (weak) undefined sym.  */
00664          elf_machine_fixup_plt (NULL, map, reloc, reloc_addr, 
00665                              DL_FIXUP_MAKE_VALUE(map, value));
00666         }
00667       return;
00668 
00669     case R_PARISC_COPY:
00670       if (__builtin_expect (sym == NULL, 0))
00671        /* This can happen in trace mode if an object could not be
00672           found.  */
00673        break;
00674       if (__builtin_expect (sym->st_size > refsym->st_size, 0)
00675          || (__builtin_expect (sym->st_size < refsym->st_size, 0)
00676              && __builtin_expect (GLRO(dl_verbose), 0)))
00677        {
00678          const char *strtab;
00679 
00680          strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
00681          _dl_error_printf ("%s: Symbol `%s' has different size in shared object, "
00682                          "consider re-linking\n",
00683                          rtld_progname ?: "<program name unknown>",
00684                          strtab + refsym->st_name);
00685        }
00686       memcpy (reloc_addr_arg, (void *) value,
00687              MIN (sym->st_size, refsym->st_size));
00688       return;
00689 
00690 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP)
00691     case R_PARISC_TLS_DTPMOD32:
00692       value = sym_map->l_tls_modid;
00693       break;
00694 
00695     case R_PARISC_TLS_DTPOFF32:
00696       /* During relocation all TLS symbols are defined and used.
00697          Therefore the offset is already correct.  */
00698       if (sym != NULL)
00699         *reloc_addr = sym->st_value;
00700       return;
00701 
00702     case R_PARISC_TLS_TPREL32:
00703       /* The offset is negative, forward from the thread pointer */
00704       if (sym != NULL)
00705         {
00706           CHECK_STATIC_TLS (map, sym_map);
00707          value = sym_map->l_tls_offset + sym->st_value + reloc->r_addend;
00708        }
00709       break;
00710 #endif /* use TLS */
00711       
00712     case R_PARISC_NONE:     /* Alright, Wilbur. */
00713       return;
00714 
00715     default:
00716       _dl_reloc_bad_type (map, r_type, 0);
00717     }
00718 
00719   *reloc_addr = value;
00720 }
00721 
00722 /* hppa doesn't have an R_PARISC_RELATIVE reloc, but uses relocs with
00723    ELF32_R_SYM (info) == 0 for a similar purpose.  */
00724 auto void __attribute__((always_inline))
00725 elf_machine_rela_relative (Elf32_Addr l_addr,
00726                         const Elf32_Rela *reloc,
00727                         void *const reloc_addr_arg)
00728 {
00729   unsigned long const r_type = ELF32_R_TYPE (reloc->r_info);
00730   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00731   static char msgbuf[] = { "Unknown" }; 
00732   struct link_map map;
00733   Elf32_Addr value;
00734 
00735   value = l_addr + reloc->r_addend;
00736 
00737   if (ELF32_R_SYM (reloc->r_info) != 0){ 
00738     _dl_error_printf ("%s: In elf_machine_rela_relative "
00739                     "ELF32_R_SYM (reloc->r_info) != 0. Aborting.",
00740                     rtld_progname ?: "<program name unknown>");
00741     ABORT_INSTRUCTION;  /* Crash. */
00742   }
00743 
00744   switch (r_type)
00745     {
00746     case R_PARISC_DIR32:
00747       /* .eh_frame can have unaligned relocs.  */
00748       if ((unsigned long) reloc_addr_arg & 3)
00749        {
00750          char *rel_addr = (char *) reloc_addr_arg;
00751          rel_addr[0] = value >> 24;
00752          rel_addr[1] = value >> 16;
00753          rel_addr[2] = value >> 8;
00754          rel_addr[3] = value;
00755          return;
00756        }
00757       break;
00758 
00759     case R_PARISC_PLABEL32:
00760       break;
00761 
00762     case R_PARISC_IPLT: /* elf_machine_runtime_setup already set gp */
00763       break;
00764 
00765     case R_PARISC_NONE:
00766       return;
00767 
00768     default: /* Bad reloc, map unknown (really it's the current map) */
00769       map.l_name = msgbuf;
00770       _dl_reloc_bad_type (&map, r_type, 0);
00771       return;
00772     }
00773 
00774   *reloc_addr = value;
00775 }
00776 
00777 auto void __attribute__((always_inline))
00778 elf_machine_lazy_rel (struct link_map *map,
00779                     Elf32_Addr l_addr, const Elf32_Rela *reloc)
00780 {
00781   /* We don't have anything to do here.  elf_machine_runtime_setup has
00782      done all the relocs already.  */
00783 }
00784 
00785 #endif /* RESOLVE_MAP */