dl-elf.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. struct r_scope_elem;
  16. #include <dl-defs.h>
  17. #ifdef __LDSO_CACHE_SUPPORT__
  18. extern int _dl_map_cache(void);
  19. extern int _dl_unmap_cache(void);
  20. #else
  21. static __inline__ void _dl_map_cache(void) { }
  22. static __inline__ void _dl_unmap_cache(void) { }
  23. #endif
  24. #define DL_RESOLVE_SECURE 0x0001
  25. #define DL_RESOLVE_NOLOAD 0x0002
  26. /* Function prototypes for non-static stuff in readelflib1.c */
  27. extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
  28. unsigned long rel_addr, unsigned long rel_size);
  29. extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
  30. struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
  31. extern struct elf_resolve * _dl_load_shared_library(unsigned rflags,
  32. struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
  33. int trace_loaded_objects);
  34. extern struct elf_resolve * _dl_load_elf_shared_library(unsigned rflags,
  35. struct dyn_elf **rpnt, const char *libname);
  36. extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
  37. int trace_loaded_objects);
  38. extern int _dl_linux_resolve(void);
  39. extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
  40. extern void _dl_protect_relro (struct elf_resolve *l);
  41. /*
  42. * Bitsize related settings for things ElfW()
  43. * does not handle already
  44. */
  45. #if __WORDSIZE == 64
  46. # define ELF_ST_BIND(val) ELF64_ST_BIND(val)
  47. # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
  48. # define ELF_R_SYM(i) ELF64_R_SYM(i)
  49. # define ELF_R_TYPE(i) ELF64_R_TYPE(i)
  50. # ifndef ELF_CLASS
  51. # define ELF_CLASS ELFCLASS64
  52. # endif
  53. #else
  54. # define ELF_ST_BIND(val) ELF32_ST_BIND(val)
  55. # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
  56. # define ELF_R_SYM(i) ELF32_R_SYM(i)
  57. # define ELF_R_TYPE(i) ELF32_R_TYPE(i)
  58. # ifndef ELF_CLASS
  59. # define ELF_CLASS ELFCLASS32
  60. # endif
  61. #endif
  62. /*
  63. * Datatype of a relocation on this platform
  64. */
  65. #ifdef ELF_USES_RELOCA
  66. # define ELF_RELOC ElfW(Rela)
  67. # define DT_RELOC_TABLE_ADDR DT_RELA
  68. # define DT_RELOC_TABLE_SIZE DT_RELASZ
  69. # define DT_RELOCCOUNT DT_RELACOUNT
  70. # define UNSUPPORTED_RELOC_TYPE DT_REL
  71. # define UNSUPPORTED_RELOC_STR "REL"
  72. #else
  73. # define ELF_RELOC ElfW(Rel)
  74. # define DT_RELOC_TABLE_ADDR DT_REL
  75. # define DT_RELOC_TABLE_SIZE DT_RELSZ
  76. # define DT_RELOCCOUNT DT_RELCOUNT
  77. # define UNSUPPORTED_RELOC_TYPE DT_RELA
  78. # define UNSUPPORTED_RELOC_STR "RELA"
  79. #endif
  80. /* OS and/or GNU dynamic extensions */
  81. #define OS_NUM_BASE 1 /* for DT_RELOCCOUNT */
  82. #ifdef __LDSO_GNU_HASH_SUPPORT__
  83. # define OS_NUM_GNU_HASH 1 /* for DT_GNU_HASH entry */
  84. #else
  85. # define OS_NUM_GNU_HASH 0
  86. #endif
  87. #ifdef __LDSO_PRELINK_SUPPORT__
  88. # define OS_NUM_PRELINK 6 /* for DT_GNU_PRELINKED entry */
  89. #else
  90. # define OS_NUM_PRELINK 0
  91. #endif
  92. #define OS_NUM (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK)
  93. #ifndef ARCH_DYNAMIC_INFO
  94. /* define in arch specific code, if needed */
  95. # define ARCH_NUM 0
  96. #endif
  97. #define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
  98. /* Keep ARCH specific entries into dynamic section at the end of the array */
  99. #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
  100. #ifdef __LDSO_GNU_HASH_SUPPORT__
  101. /* GNU hash comes just after the relocation count */
  102. # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
  103. #else
  104. # define DT_GNU_HASH_IDX DT_RELCONT_IDX
  105. #endif
  106. #ifdef __LDSO_PRELINK_SUPPORT__
  107. /* GNU prelink comes just after the GNU hash if present */
  108. #define DT_GNU_PRELINKED_IDX (DT_GNU_HASH_IDX + 1)
  109. #define DT_GNU_CONFLICT_IDX (DT_GNU_HASH_IDX + 2)
  110. #define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3)
  111. #define DT_GNU_LIBLIST_IDX (DT_GNU_HASH_IDX + 4)
  112. #define DT_GNU_LIBLISTSZ_IDX (DT_GNU_HASH_IDX + 5)
  113. #define DT_CHECKSUM_IDX (DT_GNU_HASH_IDX + 6)
  114. #endif
  115. extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
  116. void *debug_addr, DL_LOADADDR_TYPE load_off);
  117. static __always_inline
  118. unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
  119. void *debug_addr, DL_LOADADDR_TYPE load_off)
  120. {
  121. unsigned int rtld_flags = 0;
  122. for (; dpnt->d_tag; dpnt++) {
  123. if (dpnt->d_tag < DT_NUM) {
  124. dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
  125. #ifndef __mips__
  126. /* we disable for mips because normally this page is readonly
  127. * and modifying the value here needlessly dirties a page.
  128. * see this post for more info:
  129. * http://uclibc.org/lists/uclibc/2006-April/015224.html */
  130. if (dpnt->d_tag == DT_DEBUG)
  131. dpnt->d_un.d_val = (unsigned long)debug_addr;
  132. #endif
  133. if (dpnt->d_tag == DT_BIND_NOW)
  134. dynamic_info[DT_BIND_NOW] = 1;
  135. if (dpnt->d_tag == DT_FLAGS &&
  136. (dpnt->d_un.d_val & DF_BIND_NOW))
  137. dynamic_info[DT_BIND_NOW] = 1;
  138. if (dpnt->d_tag == DT_TEXTREL)
  139. dynamic_info[DT_TEXTREL] = 1;
  140. #ifdef __LDSO_RUNPATH__
  141. if (dpnt->d_tag == DT_RUNPATH)
  142. dynamic_info[DT_RPATH] = 0;
  143. if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
  144. dynamic_info[DT_RPATH] = 0;
  145. #endif
  146. } else if (dpnt->d_tag < DT_LOPROC) {
  147. if (dpnt->d_tag == DT_RELOCCOUNT)
  148. dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
  149. if (dpnt->d_tag == DT_FLAGS_1) {
  150. if (dpnt->d_un.d_val & DF_1_NOW)
  151. dynamic_info[DT_BIND_NOW] = 1;
  152. if (dpnt->d_un.d_val & DF_1_NODELETE)
  153. rtld_flags |= RTLD_NODELETE;
  154. }
  155. #ifdef __LDSO_GNU_HASH_SUPPORT__
  156. if (dpnt->d_tag == DT_GNU_HASH)
  157. dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
  158. #endif
  159. #ifdef __LDSO_PRELINK_SUPPORT__
  160. if (dpnt->d_tag == DT_GNU_PRELINKED)
  161. dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val;
  162. if (dpnt->d_tag == DT_GNU_CONFLICT)
  163. dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr;
  164. if (dpnt->d_tag == DT_GNU_CONFLICTSZ)
  165. dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val;
  166. if (dpnt->d_tag == DT_GNU_LIBLIST)
  167. dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr;
  168. if (dpnt->d_tag == DT_GNU_LIBLISTSZ)
  169. dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val;
  170. if (dpnt->d_tag == DT_CHECKSUM)
  171. dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val;
  172. #endif
  173. }
  174. #ifdef ARCH_DYNAMIC_INFO
  175. else {
  176. ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
  177. }
  178. #endif
  179. }
  180. #define ADJUST_DYN_INFO(tag, load_off) \
  181. do { \
  182. if (dynamic_info[tag]) \
  183. dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
  184. } while (0)
  185. /* Don't adjust .dynamic unnecessarily. For FDPIC targets,
  186. we'd have to walk all the loadsegs to find out if it was
  187. actually unnecessary, so skip this optimization. */
  188. #if !defined __FDPIC__ && !defined __DSBT__
  189. if (load_off != 0)
  190. #endif
  191. {
  192. ADJUST_DYN_INFO(DT_HASH, load_off);
  193. ADJUST_DYN_INFO(DT_PLTGOT, load_off);
  194. ADJUST_DYN_INFO(DT_STRTAB, load_off);
  195. ADJUST_DYN_INFO(DT_SYMTAB, load_off);
  196. ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
  197. ADJUST_DYN_INFO(DT_JMPREL, load_off);
  198. #ifdef __LDSO_GNU_HASH_SUPPORT__
  199. ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
  200. #endif
  201. }
  202. #ifdef __DSBT__
  203. /* Get the mapped address of the DSBT base. */
  204. ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
  205. #endif
  206. #undef ADJUST_DYN_INFO
  207. return rtld_flags;
  208. }
  209. /* Reloc type classes as returned by elf_machine_type_class().
  210. ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
  211. some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
  212. satisfied by any symbol in the executable. Some architectures do
  213. not support copy relocations. In this case we define the macro to
  214. zero so that the code for handling them gets automatically optimized
  215. out. */
  216. #ifdef DL_NO_COPY_RELOCS
  217. # define ELF_RTYPE_CLASS_COPY (0x0)
  218. #else
  219. # define ELF_RTYPE_CLASS_COPY (0x2)
  220. #endif
  221. #define ELF_RTYPE_CLASS_PLT (0x1)
  222. /* dlsym() calls _dl_find_hash with this value, that enables
  223. DL_FIND_HASH_VALUE to return something different than the symbol
  224. itself, e.g., a function descriptor. */
  225. #define ELF_RTYPE_CLASS_DLSYM 0x80000000
  226. /* Convert between the Linux flags for page protections and the
  227. ones specified in the ELF standard. */
  228. #define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
  229. (((X) & PF_W) ? PROT_WRITE : 0) | \
  230. (((X) & PF_X) ? PROT_EXEC : 0))
  231. #endif /* LINUXELF_H */