Back to index

glibc  2.9
do-rel.h
Go to the documentation of this file.
00001 /* Do relocations for ELF dynamic linking.
00002    Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /* This file may be included twice, to define both
00021    `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.  */
00022 
00023 #ifdef DO_RELA
00024 # define elf_dynamic_do_rel        elf_dynamic_do_rela
00025 # define RELCOUNT_IDX                     VERSYMIDX (DT_RELACOUNT)
00026 # define Rel                       Rela
00027 # define elf_machine_rel           elf_machine_rela
00028 # define elf_machine_rel_relative  elf_machine_rela_relative
00029 #else
00030 # define RELCOUNT_IDX                     VERSYMIDX (DT_RELCOUNT)
00031 #endif
00032 
00033 #ifndef DO_ELF_MACHINE_REL_RELATIVE
00034 # define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
00035   elf_machine_rel_relative (l_addr, relative,                               \
00036                          (void *) (l_addr + relative->r_offset))
00037 #endif
00038 
00039 #ifndef VERSYMIDX
00040 # define VERSYMIDX(sym)     (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
00041 #endif
00042 #ifndef VALIDX
00043 # define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
00044                     + DT_EXTRANUM + DT_VALTAGIDX (tag))
00045 #endif
00046 
00047 /* Perform the relocations in MAP on the running program image as specified
00048    by RELTAG, SZTAG.  If LAZY is nonzero, this is the first pass on PLT
00049    relocations; they should be set up to call _dl_runtime_resolve, rather
00050    than fully resolved now.  */
00051 
00052 auto inline void __attribute__ ((always_inline))
00053 elf_dynamic_do_rel (struct link_map *map,
00054                   ElfW(Addr) reladdr, ElfW(Addr) relsize,
00055                   int lazy)
00056 {
00057   const ElfW(Rel) *r = (const void *) reladdr;
00058   const ElfW(Rel) *end = (const void *) (reladdr + relsize);
00059   ElfW(Addr) l_addr = map->l_addr;
00060 
00061 #if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
00062   /* We never bind lazily during ld.so bootstrap.  Unfortunately gcc is
00063      not clever enough to see through all the function calls to realize
00064      that.  */
00065   if (lazy)
00066     {
00067       /* Doing lazy PLT relocations; they need very little info.  */
00068       for (; r < end; ++r)
00069        elf_machine_lazy_rel (map, l_addr, r);
00070     }
00071   else
00072 #endif
00073     {
00074       const ElfW(Sym) *const symtab =
00075        (const void *) D_PTR (map, l_info[DT_SYMTAB]);
00076       ElfW(Word) nrelative = (map->l_info[RELCOUNT_IDX] == NULL
00077                            ? 0 : map->l_info[RELCOUNT_IDX]->d_un.d_val);
00078       const ElfW(Rel) *relative = r;
00079       r = r + MIN (nrelative, relsize / sizeof (ElfW(Rel)));
00080 
00081 #ifndef RTLD_BOOTSTRAP
00082       /* This is defined in rtld.c, but nowhere in the static libc.a; make
00083         the reference weak so static programs can still link.  This
00084         declaration cannot be done when compiling rtld.c (i.e. #ifdef
00085         RTLD_BOOTSTRAP) because rtld.c contains the common defn for
00086         _dl_rtld_map, which is incompatible with a weak decl in the same
00087         file.  */
00088 # ifndef SHARED
00089       weak_extern (GL(dl_rtld_map));
00090 # endif
00091       if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
00092 # if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE
00093        /* Rela platforms get the offset from r_addend and this must
00094           be copied in the relocation address.  Therefore we can skip
00095           the relative relocations only if this is for rel
00096           relocations or rela relocations if they are computed as
00097           memory_loc += l_addr...  */
00098        if (l_addr != 0)
00099 # else
00100        /* ...or we know the object has been prelinked.  */
00101        if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
00102 # endif
00103 #endif
00104          for (; relative < r; ++relative)
00105            DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
00106 
00107 #ifdef RTLD_BOOTSTRAP
00108       /* The dynamic linker always uses versioning.  */
00109       assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
00110 #else
00111       if (map->l_info[VERSYMIDX (DT_VERSYM)])
00112 #endif
00113        {
00114          const ElfW(Half) *const version =
00115            (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
00116 
00117          for (; r < end; ++r)
00118            {
00119              ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
00120              elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
00121                             &map->l_versions[ndx],
00122                             (void *) (l_addr + r->r_offset));
00123            }
00124        }
00125 #ifndef RTLD_BOOTSTRAP
00126       else
00127        for (; r < end; ++r)
00128          elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
00129                         (void *) (l_addr + r->r_offset));
00130 #endif
00131     }
00132 }
00133 
00134 #undef elf_dynamic_do_rel
00135 #undef Rel
00136 #undef elf_machine_rel
00137 #undef elf_machine_rel_relative
00138 #undef DO_ELF_MACHINE_REL_RELATIVE
00139 #undef RELCOUNT_IDX