dl-elf.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
  4. *
  5. * GNU Lesser General Public License version 2.1 or later.
  6. */
  7. #ifndef LINUXELF_H
  8. #define LINUXELF_H
  9. #include <dl-string.h> /* before elf.h to get ELF_USES_RELOCA right */
  10. #include <elf.h>
  11. #include <link.h>
  12. /* Forward declarations for stuff defined in ld_hash.h */
  13. struct dyn_elf;
  14. struct elf_resolve;
  15. #include <dl-defs.h>
  16. #ifdef __LDSO_CACHE_SUPPORT__
  17. extern int _dl_map_cache(void);
  18. extern int _dl_unmap_cache(void);
  19. #else
  20. static __inline__ void _dl_map_cache(void) { }
  21. static __inline__ void _dl_unmap_cache(void) { }
  22. #endif
  23. /* Function prototypes for non-static stuff in readelflib1.c */
  24. extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
  25. unsigned long rel_addr, unsigned long rel_size);
  26. extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
  27. unsigned long rel_addr, unsigned long rel_size);
  28. extern struct elf_resolve * _dl_load_shared_library(int secure,
  29. struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
  30. int trace_loaded_objects);
  31. extern struct elf_resolve * _dl_load_elf_shared_library(int secure,
  32. struct dyn_elf **rpnt, char *libname);
  33. extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
  34. int trace_loaded_objects);
  35. extern int _dl_linux_resolve(void);
  36. extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
  37. extern void _dl_protect_relro (struct elf_resolve *l);
  38. /*
  39. * Bitsize related settings for things ElfW()
  40. * does not handle already
  41. */
  42. #if __WORDSIZE == 64
  43. # define ELF_ST_BIND(val) ELF64_ST_BIND(val)
  44. # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
  45. # define ELF_R_SYM(i) ELF64_R_SYM(i)
  46. # define ELF_R_TYPE(i) ELF64_R_TYPE(i)
  47. # ifndef ELF_CLASS
  48. # define ELF_CLASS ELFCLASS64
  49. # endif
  50. #else
  51. # define ELF_ST_BIND(val) ELF32_ST_BIND(val)
  52. # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
  53. # define ELF_R_SYM(i) ELF32_R_SYM(i)
  54. # define ELF_R_TYPE(i) ELF32_R_TYPE(i)
  55. # ifndef ELF_CLASS
  56. # define ELF_CLASS ELFCLASS32
  57. # endif
  58. #endif
  59. /*
  60. * Datatype of a relocation on this platform
  61. */
  62. #ifdef ELF_USES_RELOCA
  63. # define ELF_RELOC ElfW(Rela)
  64. # define DT_RELOC_TABLE_ADDR DT_RELA
  65. # define DT_RELOC_TABLE_SIZE DT_RELASZ
  66. # define DT_RELOCCOUNT DT_RELACOUNT
  67. # define UNSUPPORTED_RELOC_TYPE DT_REL
  68. # define UNSUPPORTED_RELOC_STR "REL"
  69. #else
  70. # define ELF_RELOC ElfW(Rel)
  71. # define DT_RELOC_TABLE_ADDR DT_REL
  72. # define DT_RELOC_TABLE_SIZE DT_RELSZ
  73. # define DT_RELOCCOUNT DT_RELCOUNT
  74. # define UNSUPPORTED_RELOC_TYPE DT_RELA
  75. # define UNSUPPORTED_RELOC_STR "RELA"
  76. #endif
  77. /* OS and/or GNU dynamic extensions */
  78. #ifdef __LDSO_GNU_HASH_SUPPORT__
  79. # define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */
  80. #else
  81. # define OS_NUM 1 /* for DT_RELOCCOUNT entry */
  82. #endif
  83. #ifndef ARCH_DYNAMIC_INFO
  84. /* define in arch specific code, if needed */
  85. # define ARCH_NUM 0
  86. #endif
  87. #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
  88. /* Keep ARCH specific entries into dynamic section at the end of the array */
  89. #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
  90. #ifdef __LDSO_GNU_HASH_SUPPORT__
  91. /* GNU hash comes just after the relocation count */
  92. # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
  93. #endif
  94. extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
  95. void *debug_addr, DL_LOADADDR_TYPE load_off);
  96. static __always_inline
  97. unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
  98. void *debug_addr, DL_LOADADDR_TYPE load_off)
  99. {
  100. unsigned int rtld_flags = 0;
  101. for (; dpnt->d_tag; dpnt++) {
  102. if (dpnt->d_tag < DT_NUM) {
  103. dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
  104. #ifndef __mips__
  105. /* we disable for mips because normally this page is readonly
  106. * and modifying the value here needlessly dirties a page.
  107. * see this post for more info:
  108. * http://uclibc.org/lists/uclibc/2006-April/015224.html */
  109. if (dpnt->d_tag == DT_DEBUG)
  110. dpnt->d_un.d_val = (unsigned long)debug_addr;
  111. #endif
  112. if (dpnt->d_tag == DT_BIND_NOW)
  113. dynamic_info[DT_BIND_NOW] = 1;
  114. if (dpnt->d_tag == DT_FLAGS &&
  115. (dpnt->d_un.d_val & DF_BIND_NOW))
  116. dynamic_info[DT_BIND_NOW] = 1;
  117. if (dpnt->d_tag == DT_TEXTREL)
  118. dynamic_info[DT_TEXTREL] = 1;
  119. #ifdef __LDSO_RUNPATH__
  120. if (dpnt->d_tag == DT_RUNPATH)
  121. dynamic_info[DT_RPATH] = 0;
  122. if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
  123. dynamic_info[DT_RPATH] = 0;
  124. #endif
  125. } else if (dpnt->d_tag < DT_LOPROC) {
  126. if (dpnt->d_tag == DT_RELOCCOUNT)
  127. dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
  128. if (dpnt->d_tag == DT_FLAGS_1) {
  129. if (dpnt->d_un.d_val & DF_1_NOW)
  130. dynamic_info[DT_BIND_NOW] = 1;
  131. if (dpnt->d_un.d_val & DF_1_NODELETE)
  132. rtld_flags |= RTLD_NODELETE;
  133. }
  134. #ifdef __LDSO_GNU_HASH_SUPPORT__
  135. if (dpnt->d_tag == DT_GNU_HASH)
  136. dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
  137. #endif
  138. }
  139. #ifdef ARCH_DYNAMIC_INFO
  140. else {
  141. ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
  142. }
  143. #endif
  144. }
  145. #define ADJUST_DYN_INFO(tag, load_off) \
  146. do { \
  147. if (dynamic_info[tag]) \
  148. dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
  149. } while (0)
  150. /* Don't adjust .dynamic unnecessarily. */
  151. if (load_off != 0) {
  152. ADJUST_DYN_INFO(DT_HASH, load_off);
  153. ADJUST_DYN_INFO(DT_PLTGOT, load_off);
  154. ADJUST_DYN_INFO(DT_STRTAB, load_off);
  155. ADJUST_DYN_INFO(DT_SYMTAB, load_off);
  156. ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
  157. ADJUST_DYN_INFO(DT_JMPREL, load_off);
  158. #ifdef __LDSO_GNU_HASH_SUPPORT__
  159. ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
  160. #endif
  161. }
  162. #undef ADJUST_DYN_INFO
  163. return rtld_flags;
  164. }
  165. /* Reloc type classes as returned by elf_machine_type_class().
  166. ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
  167. some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
  168. satisfied by any symbol in the executable. Some architectures do
  169. not support copy relocations. In this case we define the macro to
  170. zero so that the code for handling them gets automatically optimized
  171. out. */
  172. #ifdef DL_NO_COPY_RELOCS
  173. # define ELF_RTYPE_CLASS_COPY (0x0)
  174. #else
  175. # define ELF_RTYPE_CLASS_COPY (0x2)
  176. #endif
  177. #define ELF_RTYPE_CLASS_PLT (0x1)
  178. /* dlsym() calls _dl_find_hash with this value, that enables
  179. DL_FIND_HASH_VALUE to return something different than the symbol
  180. itself, e.g., a function descriptor. */
  181. #define ELF_RTYPE_CLASS_DLSYM 0x80000000
  182. /* Convert between the Linux flags for page protections and the
  183. ones specified in the ELF standard. */
  184. #define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
  185. (((X) & PF_W) ? PROT_WRITE : 0) | \
  186. (((X) & PF_X) ? PROT_EXEC : 0))
  187. #endif /* LINUXELF_H */