Back to index

glibc  2.9
dl-machine.h
Go to the documentation of this file.
00001 /* Machine-dependent ELF dynamic relocation inline functions.  ARM version.
00002    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef dl_machine_h
00022 #define dl_machine_h
00023 
00024 #define ELF_MACHINE_NAME "ARM"
00025 
00026 #include <sys/param.h>
00027 #include <tls.h>
00028 
00029 #define VALID_ELF_ABIVERSION(ver)  (ver == 0)
00030 #define VALID_ELF_OSABI(osabi) \
00031   (osabi == ELFOSABI_SYSV || osabi == ELFOSABI_ARM)
00032 #define VALID_ELF_HEADER(hdr,exp,size) \
00033   memcmp (hdr,exp,size-2) == 0 \
00034   && VALID_ELF_OSABI (hdr[EI_OSABI]) \
00035   && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
00036 
00037 #define CLEAR_CACHE(BEG,END)                                          \
00038   INTERNAL_SYSCALL_ARM (cacheflush, , 3, (BEG), (END), 0)
00039 
00040 /* Return nonzero iff ELF header is compatible with the running host.  */
00041 static inline int __attribute__ ((unused))
00042 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
00043 {
00044   return ehdr->e_machine == EM_ARM;
00045 }
00046 
00047 
00048 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
00049    first element of the GOT.  We used to use the PIC register to do this
00050    without a constant pool reference, but GCC 4.2 will use a pseudo-register
00051    for the PIC base, so it may not be in r10.  */
00052 static inline Elf32_Addr __attribute__ ((unused))
00053 elf_machine_dynamic (void)
00054 {
00055   Elf32_Addr dynamic;
00056   asm ("ldr %0, 2f\n"
00057        "1: ldr %0, [pc, %0]\n"
00058        "b 3f\n"
00059        "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
00060        "3:" : "=r" (dynamic));
00061   return dynamic;
00062 }
00063 
00064 
00065 /* Return the run-time load address of the shared object.  */
00066 static inline Elf32_Addr __attribute__ ((unused))
00067 elf_machine_load_address (void)
00068 {
00069   extern void __dl_start asm ("_dl_start");
00070   Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
00071   Elf32_Addr pcrel_addr;
00072   asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
00073   return pcrel_addr - got_addr;
00074 }
00075 
00076 
00077 /* Set up the loaded object described by L so its unrelocated PLT
00078    entries will jump to the on-demand fixup code in dl-runtime.c.  */
00079 
00080 static inline int __attribute__ ((unused))
00081 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
00082 {
00083   Elf32_Addr *got;
00084   extern void _dl_runtime_resolve (Elf32_Word);
00085   extern void _dl_runtime_profile (Elf32_Word);
00086 
00087   if (l->l_info[DT_JMPREL] && lazy)
00088     {
00089       /* patb: this is different than i386 */
00090       /* The GOT entries for functions in the PLT have not yet been filled
00091         in.  Their initial contents will arrange when called to push an
00092         index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
00093         and then jump to _GLOBAL_OFFSET_TABLE[2].  */
00094       got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
00095       /* If a library is prelinked but we have to relocate anyway,
00096         we have to be able to undo the prelinking of .got.plt.
00097         The prelinker saved us here address of .plt.  */
00098       if (got[1])
00099        l->l_mach.plt = got[1] + l->l_addr;
00100       got[1] = (Elf32_Addr) l;     /* Identify this shared object.  */
00101 
00102       /* The got[2] entry contains the address of a function which gets
00103         called to get the address of a so far unresolved function and
00104         jump to it.  The profiling extension of the dynamic linker allows
00105         to intercept the calls to collect information.  In this case we
00106         don't store the address in the GOT so that all future calls also
00107         end in this function.  */
00108       if (profile)
00109        {
00110          got[2] = (Elf32_Addr) &_dl_runtime_profile;
00111 
00112          if (GLRO(dl_profile) != NULL
00113              && _dl_name_match_p (GLRO(dl_profile), l))
00114            /* Say that we really want profiling and the timers are
00115               started.  */
00116            GL(dl_profile_map) = l;
00117        }
00118       else
00119        /* This function will get called to fix up the GOT entry indicated by
00120           the offset on the stack, and then jump to the resolved address.  */
00121        got[2] = (Elf32_Addr) &_dl_runtime_resolve;
00122     }
00123   return lazy;
00124 }
00125 
00126 #if defined(__USE_BX__)
00127 #define BX(x) "bx\t" #x
00128 #else
00129 #define BX(x) "mov\tpc, " #x
00130 #endif
00131 
00132 /* Mask identifying addresses reserved for the user program,
00133    where the dynamic linker should not map anything.  */
00134 #define ELF_MACHINE_USER_ADDRESS_MASK     0xf8000000UL
00135 
00136 /* Initial entry point code for the dynamic linker.
00137    The C function `_dl_start' is the real entry point;
00138    its return value is the user program's entry point.  */
00139 
00140 #define RTLD_START asm ("\
00141 .text\n\
00142 .globl _start\n\
00143 .globl _dl_start_user\n\
00144 _start:\n\
00145        @ we are PIC code, so get global offset table\n\
00146        ldr    sl, .L_GET_GOT\n\
00147        @ See if we were run as a command with the executable file\n\
00148        @ name as an extra leading argument.\n\
00149        ldr    r4, .L_SKIP_ARGS\n\
00150        @ at start time, all the args are on the stack\n\
00151        mov    r0, sp\n\
00152        bl     _dl_start\n\
00153        @ returns user entry point in r0\n\
00154 _dl_start_user:\n\
00155        add    sl, pc, sl\n\
00156 .L_GOT_GOT:\n\
00157        ldr    r4, [sl, r4]\n\
00158        @ save the entry point in another register\n\
00159        mov    r6, r0\n\
00160        @ get the original arg count\n\
00161        ldr    r1, [sp]\n\
00162        @ get the argv address\n\
00163        add    r2, sp, #4\n\
00164        @ Fix up the stack if necessary.\n\
00165        cmp    r4, #0\n\
00166        bne    .L_fixup_stack\n\
00167 .L_done_fixup:\n\
00168        @ compute envp\n\
00169        add    r3, r2, r1, lsl #2\n\
00170        add    r3, r3, #4\n\
00171        @ now we call _dl_init\n\
00172        ldr    r0, .L_LOADED\n\
00173        ldr    r0, [sl, r0]\n\
00174        @ call _dl_init\n\
00175        bl     _dl_init_internal(PLT)\n\
00176        @ load the finalizer function\n\
00177        ldr    r0, .L_FINI_PROC\n\
00178        add    r0, sl, r0\n\
00179        @ jump to the user_s entry point\n\
00180        " BX(r6) "\n\
00181 \n\
00182        @ iWMMXt and EABI targets require the stack to be eight byte\n\
00183        @ aligned - shuffle arguments etc.\n\
00184 .L_fixup_stack:\n\
00185        @ subtract _dl_skip_args from original arg count\n\
00186        sub    r1, r1, r4\n\
00187        @ store the new argc in the new stack location\n\
00188        str    r1, [sp]\n\
00189        @ find the first unskipped argument\n\
00190        mov    r3, r2\n\
00191        add    r4, r2, r4, lsl #2\n\
00192        @ shuffle argv down\n\
00193 1:     ldr    r5, [r4], #4\n\
00194        str    r5, [r3], #4\n\
00195        cmp    r5, #0\n\
00196        bne    1b\n\
00197        @ shuffle envp down\n\
00198 1:     ldr    r5, [r4], #4\n\
00199        str    r5, [r3], #4\n\
00200        cmp    r5, #0\n\
00201        bne    1b\n\
00202        @ shuffle auxv down\n\
00203 1:     ldmia  r4!, {r0, r5}\n\
00204        stmia  r3!, {r0, r5}\n\
00205        cmp    r0, #0\n\
00206        bne    1b\n\
00207        @ Update _dl_argv\n\
00208        ldr    r3, .L_ARGV\n\
00209        str    r2, [sl, r3]\n\
00210        b      .L_done_fixup\n\
00211 \n\
00212 .L_GET_GOT:\n\
00213        .word  _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n\
00214 .L_SKIP_ARGS:\n\
00215        .word  _dl_skip_args(GOTOFF)\n\
00216 .L_FINI_PROC:\n\
00217        .word  _dl_fini(GOTOFF)\n\
00218 .L_ARGV:\n\
00219        .word  _dl_argv(GOTOFF)\n\
00220 .L_LOADED:\n\
00221        .word  _rtld_local(GOTOFF)\n\
00222 .previous\n\
00223 ");
00224 
00225 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
00226    TLS variable, so undefined references should not be allowed to
00227    define the value.
00228    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
00229    of the main executable's symbols, as for a COPY reloc.  */
00230 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
00231 # define elf_machine_type_class(type) \
00232   ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32        \
00233      || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32)  \
00234     * ELF_RTYPE_CLASS_PLT)                                     \
00235    | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
00236 #else
00237 #define elf_machine_type_class(type) \
00238   ((((type) == R_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)  \
00239    | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
00240 #endif
00241 
00242 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
00243 #define ELF_MACHINE_JMP_SLOT       R_ARM_JUMP_SLOT
00244 
00245 /* ARM never uses Elf32_Rela relocations for the dynamic linker.
00246    Prelinked libraries may use Elf32_Rela though.  */
00247 #define ELF_MACHINE_PLT_REL 1
00248 
00249 /* We define an initialization functions.  This is called very early in
00250    _dl_sysdep_start.  */
00251 #define DL_PLATFORM_INIT dl_platform_init ()
00252 
00253 static inline void __attribute__ ((unused))
00254 dl_platform_init (void)
00255 {
00256   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
00257     /* Avoid an empty string which would disturb us.  */
00258     GLRO(dl_platform) = NULL;
00259 }
00260 
00261 static inline Elf32_Addr
00262 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
00263                      const Elf32_Rel *reloc,
00264                      Elf32_Addr *reloc_addr, Elf32_Addr value)
00265 {
00266   return *reloc_addr = value;
00267 }
00268 
00269 /* Return the final value of a plt relocation.  */
00270 static inline Elf32_Addr
00271 elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
00272                      Elf32_Addr value)
00273 {
00274   return value;
00275 }
00276 
00277 #endif /* !dl_machine_h */
00278 
00279 
00280 /* ARM never uses Elf32_Rela relocations for the dynamic linker.
00281    Prelinked libraries may use Elf32_Rela though.  */
00282 #define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
00283 
00284 /* Names of the architecture-specific auditing callback functions.  */
00285 #define ARCH_LA_PLTENTER arm_gnu_pltenter
00286 #define ARCH_LA_PLTEXIT arm_gnu_pltexit
00287 
00288 #ifdef RESOLVE_MAP
00289 
00290 /* Deal with an out-of-range PC24 reloc.  */
00291 auto Elf32_Addr
00292 fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value)
00293 {
00294   static void *fix_page;
00295   static unsigned int fix_offset;
00296   static size_t pagesize;
00297   Elf32_Word *fix_address;
00298 
00299   if (! fix_page)
00300     {
00301       if (! pagesize)
00302        pagesize = getpagesize ();
00303       fix_page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC,
00304                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
00305       if (! fix_page)
00306        assert (! "could not map page for fixup");
00307       fix_offset = 0;
00308     }
00309 
00310   fix_address = (Elf32_Word *)(fix_page + fix_offset);
00311   fix_address[0] = 0xe51ff004;     /* ldr pc, [pc, #-4] */
00312   fix_address[1] = value;
00313 
00314   fix_offset += 8;
00315   if (fix_offset >= pagesize)
00316     fix_page = NULL;
00317 
00318   return (Elf32_Addr)fix_address;
00319 }
00320 
00321 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
00322    MAP is the object containing the reloc.  */
00323 
00324 auto inline void
00325 __attribute__ ((always_inline))
00326 elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
00327                const Elf32_Sym *sym, const struct r_found_version *version,
00328                void *const reloc_addr_arg)
00329 {
00330   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00331   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
00332 
00333 #if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
00334   if (__builtin_expect (r_type == R_ARM_RELATIVE, 0))
00335     {
00336 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
00337       /* This is defined in rtld.c, but nowhere in the static libc.a;
00338         make the reference weak so static programs can still link.
00339         This declaration cannot be done when compiling rtld.c
00340         (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
00341         common defn for _dl_rtld_map, which is incompatible with a
00342         weak decl in the same file.  */
00343 #  ifndef SHARED
00344       weak_extern (_dl_rtld_map);
00345 #  endif
00346       if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
00347 # endif
00348        *reloc_addr += map->l_addr;
00349     }
00350 # ifndef RTLD_BOOTSTRAP
00351   else if (__builtin_expect (r_type == R_ARM_NONE, 0))
00352     return;
00353 # endif
00354   else
00355 #endif
00356     {
00357       const Elf32_Sym *const refsym = sym;
00358       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
00359       Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
00360 
00361       switch (r_type)
00362        {
00363        case R_ARM_COPY:
00364          if (sym == NULL)
00365            /* This can happen in trace mode if an object could not be
00366               found.  */
00367            break;
00368          if (sym->st_size > refsym->st_size
00369              || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
00370            {
00371              const char *strtab;
00372 
00373              strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
00374              _dl_error_printf ("\
00375 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
00376                             rtld_progname ?: "<program name unknown>",
00377                             strtab + refsym->st_name);
00378            }
00379          memcpy (reloc_addr_arg, (void *) value,
00380                 MIN (sym->st_size, refsym->st_size));
00381          break;
00382        case R_ARM_GLOB_DAT:
00383        case R_ARM_JUMP_SLOT:
00384 # ifdef RTLD_BOOTSTRAP
00385          /* Fix weak undefined references.  */
00386          if (sym != NULL && sym->st_value == 0)
00387            *reloc_addr = 0;
00388          else
00389 # endif
00390            *reloc_addr = value;
00391          break;
00392        case R_ARM_ABS32:
00393          {
00394 # ifndef RTLD_BOOTSTRAP
00395           /* This is defined in rtld.c, but nowhere in the static
00396              libc.a; make the reference weak so static programs can
00397              still link.  This declaration cannot be done when
00398              compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP) because
00399              rtld.c contains the common defn for _dl_rtld_map, which
00400              is incompatible with a weak decl in the same file.  */
00401 #  ifndef SHARED
00402            weak_extern (_dl_rtld_map);
00403 #  endif
00404            if (map == &GL(dl_rtld_map))
00405              /* Undo the relocation done here during bootstrapping.
00406                Now we will relocate it anew, possibly using a
00407                binding found in the user program or a loaded library
00408                rather than the dynamic linker's built-in definitions
00409                used while loading those libraries.  */
00410              value -= map->l_addr + refsym->st_value;
00411 # endif
00412            *reloc_addr += value;
00413            break;
00414          }
00415        case R_ARM_PC24:
00416          {
00417             Elf32_Sword addend;
00418             Elf32_Addr newvalue, topbits;
00419 
00420             addend = *reloc_addr & 0x00ffffff;
00421             if (addend & 0x00800000) addend |= 0xff000000;
00422 
00423             newvalue = value - (Elf32_Addr)reloc_addr + (addend << 2);
00424             topbits = newvalue & 0xfe000000;
00425             if (topbits != 0xfe000000 && topbits != 0x00000000)
00426               {
00427                newvalue = fix_bad_pc24(reloc_addr, value)
00428                  - (Elf32_Addr)reloc_addr + (addend << 2);
00429                topbits = newvalue & 0xfe000000;
00430                if (topbits != 0xfe000000 && topbits != 0x00000000)
00431                  {
00432                    _dl_signal_error (0, map->l_name, NULL,
00433                                    "R_ARM_PC24 relocation out of range");
00434                  }
00435               }
00436             newvalue >>= 2;
00437             value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
00438             *reloc_addr = value;
00439          }
00440          break;
00441 #if defined USE_TLS && !defined RTLD_BOOTSTRAP
00442        case R_ARM_TLS_DTPMOD32:
00443          /* Get the information from the link map returned by the
00444             resolv function.  */
00445          if (sym_map != NULL)
00446            *reloc_addr = sym_map->l_tls_modid;
00447          break;
00448 
00449        case R_ARM_TLS_DTPOFF32:
00450          if (sym != NULL)
00451            *reloc_addr += sym->st_value;
00452          break;
00453 
00454        case R_ARM_TLS_TPOFF32:
00455          if (sym != NULL)
00456            {
00457              CHECK_STATIC_TLS (map, sym_map);
00458              *reloc_addr += sym->st_value + sym_map->l_tls_offset;
00459            }
00460          break;
00461 #endif
00462        default:
00463          _dl_reloc_bad_type (map, r_type, 0);
00464          break;
00465        }
00466     }
00467 }
00468 
00469 # ifndef RTLD_BOOTSTRAP
00470 auto inline void
00471 __attribute__ ((always_inline))
00472 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
00473                 const Elf32_Sym *sym, const struct r_found_version *version,
00474                 void *const reloc_addr_arg)
00475 {
00476   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00477   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
00478 
00479   if (__builtin_expect (r_type == R_ARM_RELATIVE, 0))
00480     *reloc_addr = map->l_addr + reloc->r_addend;
00481   else if (__builtin_expect (r_type == R_ARM_NONE, 0))
00482     return;
00483   else
00484     {
00485 # ifndef RESOLVE_CONFLICT_FIND_MAP
00486       const Elf32_Sym *const refsym = sym;
00487 # endif
00488       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
00489       Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
00490 
00491       switch (r_type)
00492        {
00493 #  ifndef RESOLVE_CONFLICT_FIND_MAP
00494          /* Not needed for dl-conflict.c.  */
00495        case R_ARM_COPY:
00496          if (sym == NULL)
00497            /* This can happen in trace mode if an object could not be
00498               found.  */
00499            break;
00500          if (sym->st_size > refsym->st_size
00501              || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
00502            {
00503              const char *strtab;
00504 
00505              strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
00506              _dl_error_printf ("\
00507 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
00508                             rtld_progname ?: "<program name unknown>",
00509                             strtab + refsym->st_name);
00510            }
00511          memcpy (reloc_addr_arg, (void *) value,
00512                 MIN (sym->st_size, refsym->st_size));
00513          break;
00514 #  endif /* !RESOLVE_CONFLICT_FIND_MAP */
00515        case R_ARM_GLOB_DAT:
00516        case R_ARM_JUMP_SLOT:
00517        case R_ARM_ABS32:
00518          *reloc_addr = value + reloc->r_addend;
00519          break;
00520        case R_ARM_PC24:
00521          {
00522             Elf32_Addr newvalue, topbits;
00523 
00524             newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr;
00525             topbits = newvalue & 0xfe000000;
00526             if (topbits != 0xfe000000 && topbits != 0x00000000)
00527               {
00528                newvalue = fix_bad_pc24(reloc_addr, value)
00529                  - (Elf32_Addr)reloc_addr + (reloc->r_addend << 2);
00530                topbits = newvalue & 0xfe000000;
00531                if (topbits != 0xfe000000 && topbits != 0x00000000)
00532                  {
00533                    _dl_signal_error (0, map->l_name, NULL,
00534                                    "R_ARM_PC24 relocation out of range");
00535                  }
00536               }
00537             newvalue >>= 2;
00538             value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
00539             *reloc_addr = value;
00540          }
00541          break;
00542 #if defined USE_TLS && !defined RTLD_BOOTSTRAP
00543        case R_ARM_TLS_DTPMOD32:
00544          /* Get the information from the link map returned by the
00545             resolv function.  */
00546          if (sym_map != NULL)
00547            *reloc_addr = sym_map->l_tls_modid;
00548          break;
00549 
00550        case R_ARM_TLS_DTPOFF32:
00551          *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
00552          break;
00553 
00554        case R_ARM_TLS_TPOFF32:
00555          if (sym != NULL)
00556            {
00557              CHECK_STATIC_TLS (map, sym_map);
00558              *reloc_addr = (sym->st_value + sym_map->l_tls_offset
00559                           + reloc->r_addend);
00560            }
00561          break;
00562 #endif
00563        default:
00564          _dl_reloc_bad_type (map, r_type, 0);
00565          break;
00566        }
00567     }
00568 }
00569 # endif
00570 
00571 auto inline void
00572 __attribute__ ((always_inline))
00573 elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
00574                        void *const reloc_addr_arg)
00575 {
00576   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00577   *reloc_addr += l_addr;
00578 }
00579 
00580 # ifndef RTLD_BOOTSTRAP
00581 auto inline void
00582 __attribute__ ((always_inline))
00583 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
00584                         void *const reloc_addr_arg)
00585 {
00586   Elf32_Addr *const reloc_addr = reloc_addr_arg;
00587   *reloc_addr = l_addr + reloc->r_addend;
00588 }
00589 # endif
00590 
00591 auto inline void
00592 __attribute__ ((always_inline))
00593 elf_machine_lazy_rel (struct link_map *map,
00594                     Elf32_Addr l_addr, const Elf32_Rel *reloc)
00595 {
00596   Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
00597   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
00598   /* Check for unexpected PLT reloc type.  */
00599   if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1))
00600     {
00601       if (__builtin_expect (map->l_mach.plt, 0) == 0)
00602        *reloc_addr += l_addr;
00603       else
00604        *reloc_addr = map->l_mach.plt;
00605     }
00606   else
00607     _dl_reloc_bad_type (map, r_type, 1);
00608 }
00609 
00610 #endif /* RESOLVE_MAP */