(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/dynamic-link.h

    1: /* Inline functions for dynamic linking.
    2:    Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <elf.h>
   21: #include <assert.h>
   22: 
   23: #ifdef RESOLVE_MAP
   24: /* We pass reloc_addr as a pointer to void, as opposed to a pointer to
   25:    ElfW(Addr), because not all architectures can assume that the
   26:    relocated address is properly aligned, whereas the compiler is
   27:    entitled to assume that a pointer to a type is properly aligned for
   28:    the type.  Even if we cast the pointer back to some other type with
   29:    less strict alignment requirements, the compiler might still
   30:    remember that the pointer was originally more aligned, thereby
   31:    optimizing away alignment tests or using word instructions for
   32:    copying memory, breaking the very code written to handle the
   33:    unaligned cases.  */
   34: # if ! ELF_MACHINE_NO_REL
   35: auto inline void __attribute__((always_inline))
   36: elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
   37:                  const ElfW(Sym) *sym, const struct r_found_version *version,
   38:                  void *const reloc_addr);
   39: auto inline void __attribute__((always_inline))
   40: elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
   41:                           void *const reloc_addr);
   42: # endif
   43: # if ! ELF_MACHINE_NO_RELA
   44: auto inline void __attribute__((always_inline))
   45: elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
   46:                   const ElfW(Sym) *sym, const struct r_found_version *version,
   47:                   void *const reloc_addr);
   48: auto inline void __attribute__((always_inline))
   49: elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
   50:                            void *const reloc_addr);
   51: # endif
   52: # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
   53: auto inline void __attribute__((always_inline))
   54: elf_machine_lazy_rel (struct link_map *map,
   55:                       ElfW(Addr) l_addr, const ElfW(Rel) *reloc);
   56: # else
   57: auto inline void __attribute__((always_inline))
   58: elf_machine_lazy_rel (struct link_map *map,
   59:                       ElfW(Addr) l_addr, const ElfW(Rela) *reloc);
   60: # endif
   61: #endif
   62: 
   63: #include <dl-machine.h>
   64: 
   65: #ifndef VERSYMIDX
   66: # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
   67: #endif
   68: 
   69: 
   70: /* Read the dynamic section at DYN and fill in INFO with indices DT_*.  */
   71: #ifndef RESOLVE_MAP
   72: static
   73: #else
   74: auto
   75: #endif
   76: inline void __attribute__ ((unused, always_inline))
   77: elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   78: {
   79:   ElfW(Dyn) *dyn = l->l_ld;
   80:   ElfW(Dyn) **info;
   81: 
   82: #ifndef RTLD_BOOTSTRAP
   83:   if (dyn == NULL)
   84:     return;
   85: #endif
   86: 
   87:   info = l->l_info;
   88: 
   89:   while (dyn->d_tag != DT_NULL)
   90:     {
   91:       if (dyn->d_tag < DT_NUM)
   92:         info[dyn->d_tag] = dyn;
   93:       else if (dyn->d_tag >= DT_LOPROC &&
   94:                dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
   95:         info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
   96:       else if ((Elf32_Word) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
   97:         info[VERSYMIDX (dyn->d_tag)] = dyn;
   98:       else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
   99:         info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  100:              + DT_VERSIONTAGNUM] = dyn;
  101:       else if ((Elf32_Word) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
  102:         info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  103:              + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
  104:       else if ((Elf32_Word) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
  105:         info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  106:              + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
  107:       ++dyn;
  108:     }
  109: 
  110: #define DL_RO_DYN_TEMP_CNT      8
  111: 
  112: #ifndef DL_RO_DYN_SECTION
  113:   /* Don't adjust .dynamic unnecessarily.  */
  114:   if (l->l_addr != 0)
  115:     {
  116:       ElfW(Addr) l_addr = l->l_addr;
  117:       int cnt = 0;
  118: 
  119: # define ADJUST_DYN_INFO(tag) \
  120:       do                                                                      \
  121:         if (info[tag] != NULL)                                               \
  122:           {                                                                  \
  123:             if (temp)                                                        \
  124:               {                                                                      \
  125:                 temp[cnt].d_tag = info[tag]->d_tag;                         \
  126:                 temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr;              \
  127:                 info[tag] = temp + cnt++;                                   \
  128:               }                                                                      \
  129:             else                                                             \
  130:               info[tag]->d_un.d_ptr += l_addr;                               \
  131:           }                                                                  \
  132:       while (0)
  133: 
  134:       ADJUST_DYN_INFO (DT_HASH);
  135:       ADJUST_DYN_INFO (DT_PLTGOT);
  136:       ADJUST_DYN_INFO (DT_STRTAB);
  137:       ADJUST_DYN_INFO (DT_SYMTAB);
  138: # if ! ELF_MACHINE_NO_RELA
  139:       ADJUST_DYN_INFO (DT_RELA);
  140: # endif
  141: # if ! ELF_MACHINE_NO_REL
  142:       ADJUST_DYN_INFO (DT_REL);
  143: # endif
  144:       ADJUST_DYN_INFO (DT_JMPREL);
  145:       ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
  146:       ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
  147:                        + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
  148: # undef ADJUST_DYN_INFO
  149:       assert (cnt <= DL_RO_DYN_TEMP_CNT);
  150:     }
  151: #endif
  152:   if (info[DT_PLTREL] != NULL)
  153:     {
  154: #if ELF_MACHINE_NO_RELA
  155:       assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
  156: #elif ELF_MACHINE_NO_REL
  157:       assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
  158: #else
  159:       assert (info[DT_PLTREL]->d_un.d_val == DT_REL
  160:               || info[DT_PLTREL]->d_un.d_val == DT_RELA);
  161: #endif
  162:     }
  163: #if ! ELF_MACHINE_NO_RELA
  164:   if (info[DT_RELA] != NULL)
  165:     assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
  166: # endif
  167: # if ! ELF_MACHINE_NO_REL
  168:   if (info[DT_REL] != NULL)
  169:     assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
  170: #endif
  171: #ifdef RTLD_BOOTSTRAP
  172:   /* Only the bind now flags are allowed.  */
  173:   assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
  174:           || info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val == DF_1_NOW);
  175:   assert (info[DT_FLAGS] == NULL
  176:           || info[DT_FLAGS]->d_un.d_val == DF_BIND_NOW);
  177:   /* Flags must not be set for ld.so.  */
  178:   assert (info[DT_RUNPATH] == NULL);
  179:   assert (info[DT_RPATH] == NULL);
  180: #else
  181:   if (info[DT_FLAGS] != NULL)
  182:     {
  183:       /* Flags are used.  Translate to the old form where available.
  184:          Since these l_info entries are only tested for NULL pointers it
  185:          is ok if they point to the DT_FLAGS entry.  */
  186:       l->l_flags = info[DT_FLAGS]->d_un.d_val;
  187: 
  188:       if (l->l_flags & DF_SYMBOLIC)
  189:         info[DT_SYMBOLIC] = info[DT_FLAGS];
  190:       if (l->l_flags & DF_TEXTREL)
  191:         info[DT_TEXTREL] = info[DT_FLAGS];
  192:       if (l->l_flags & DF_BIND_NOW)
  193:         info[DT_BIND_NOW] = info[DT_FLAGS];
  194:     }
  195:   if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
  196:     {
  197:       l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
  198: 
  199:       if (l->l_flags_1 & DF_1_NOW)
  200:         info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)];
  201:     }
  202:   if (info[DT_RUNPATH] != NULL)
  203:     /* If both RUNPATH and RPATH are given, the latter is ignored.  */
  204:     info[DT_RPATH] = NULL;
  205: #endif
  206: }
  207: 
  208: #ifdef RESOLVE_MAP
  209: 
  210: # ifdef RTLD_BOOTSTRAP
  211: #  define ELF_DURING_STARTUP (1)
  212: # else
  213: #  define ELF_DURING_STARTUP (0)
  214: # endif
  215: 
  216: /* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
  217:    These functions are almost identical, so we use cpp magic to avoid
  218:    duplicating their code.  It cannot be done in a more general function
  219:    because we must be able to completely inline.  */
  220: 
  221: /* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
  222:    range.  Note that according to the ELF spec, this is completely legal!
  223:    But conditionally define things so that on machines we know this will
  224:    not happen we do something more optimal.  */
  225: 
  226: # ifdef ELF_MACHINE_PLTREL_OVERLAP
  227: #  define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
  228:   do {                                                                        \
  229:     struct { ElfW(Addr) start, size; int lazy; } ranges[3];                   \
  230:     int ranges_index;                                                         \
  231:                                                                               \
  232:     ranges[0].lazy = ranges[2].lazy = 0;                                      \
  233:     ranges[1].lazy = 1;                                                       \
  234:     ranges[0].size = ranges[1].size = ranges[2].size = 0;                     \
  235:                                                                               \
  236:     if ((map)->l_info[DT_##RELOC])                                            \
  237:       {                                                                       \
  238:         ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]);                 \
  239:         ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val;          \
  240:       }                                                                       \
  241:                                                                               \
  242:     if ((do_lazy)                                                             \
  243:         && (map)->l_info[DT_PLTREL]                                          \
  244:         && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
  245:       {                                                                       \
  246:         ranges[1].start = D_PTR ((map), l_info[DT_JMPREL]);                  \
  247:         ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;             \
  248:         ranges[2].start = ranges[1].start + ranges[1].size;                  \
  249:         ranges[2].size = ranges[0].start + ranges[0].size - ranges[2].start;  \
  250:         ranges[0].size = ranges[1].start - ranges[0].start;                  \
  251:       }                                                                       \
  252:                                                                               \
  253:     for (ranges_index = 0; ranges_index < 3; ++ranges_index)                  \
  254:       elf_dynamic_do_##reloc ((map),                                          \
  255:                               ranges[ranges_index].start,                  \
  256:                               ranges[ranges_index].size,                   \
  257:                               ranges[ranges_index].lazy);                  \
  258:   } while (0)
  259: # else
  260: #  define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
  261:   do {                                                                        \
  262:     struct { ElfW(Addr) start, size; int lazy; } ranges[2];                   \
  263:     ranges[0].lazy = 0;                                                       \
  264:     ranges[0].size = ranges[1].size = 0;                                      \
  265:     ranges[0].start = 0;                                                      \
  266:                                                                               \
  267:     if ((map)->l_info[DT_##RELOC])                                            \
  268:       {                                                                       \
  269:         ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]);                 \
  270:         ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val;          \
  271:       }                                                                       \
  272:     if ((map)->l_info[DT_PLTREL]                                              \
  273:         && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
  274:       {                                                                       \
  275:         ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]);                 \
  276:                                                                               \
  277:         if (! ELF_DURING_STARTUP                                             \
  278:             && ((do_lazy)                                                    \
  279:                 /* This test does not only detect whether the relocation      \
  280:                    sections are in the right order, it also checks whether    \
  281:                    there is a DT_REL/DT_RELA section.  */                   \
  282:                 || ranges[0].start + ranges[0].size != start))                      \
  283:           {                                                                  \
  284:             ranges[1].start = start;                                         \
  285:             ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;         \
  286:             ranges[1].lazy = (do_lazy);                                              \
  287:           }                                                                  \
  288:         else                                                                 \
  289:           {                                                                  \
  290:             /* Combine processing the sections.  */                          \
  291:             assert (ranges[0].start + ranges[0].size == start);                      \
  292:             ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val;        \
  293:           }                                                                  \
  294:       }                                                                       \
  295:                                                                               \
  296:     if (ELF_DURING_STARTUP)                                                   \
  297:       elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, 0);     \
  298:     else                                                                      \
  299:       {                                                                       \
  300:         int ranges_index;                                                    \
  301:         for (ranges_index = 0; ranges_index < 2; ++ranges_index)             \
  302:           elf_dynamic_do_##reloc ((map),                                     \
  303:                                   ranges[ranges_index].start,                     \
  304:                                   ranges[ranges_index].size,                      \
  305:                                   ranges[ranges_index].lazy);                     \
  306:       }                                                                       \
  307:   } while (0)
  308: # endif
  309: 
  310: # if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
  311: #  define _ELF_CHECK_REL 0
  312: # else
  313: #  define _ELF_CHECK_REL 1
  314: # endif
  315: 
  316: # if ! ELF_MACHINE_NO_REL
  317: #  include "do-rel.h"
  318: #  define ELF_DYNAMIC_DO_REL(map, lazy) \
  319:   _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
  320: # else
  321: #  define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do.  */
  322: # endif
  323: 
  324: # if ! ELF_MACHINE_NO_RELA
  325: #  define DO_RELA
  326: #  include "do-rel.h"
  327: #  define ELF_DYNAMIC_DO_RELA(map, lazy) \
  328:   _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
  329: # else
  330: #  define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do.  */
  331: # endif
  332: 
  333: /* This can't just be an inline function because GCC is too dumb
  334:    to inline functions containing inlines themselves.  */
  335: # define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
  336:   do {                                                                        \
  337:     int edr_lazy = elf_machine_runtime_setup ((map), (lazy),                  \
  338:                                               (consider_profile));       \
  339:     ELF_DYNAMIC_DO_REL ((map), edr_lazy);                                     \
  340:     ELF_DYNAMIC_DO_RELA ((map), edr_lazy);                                    \
  341:   } while (0)
  342: 
  343: #endif
Syntax (Markdown)