rel.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. #include "elf.h"
  4. #ifndef VERSYMIDX
  5. # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
  6. #endif
  7. #ifndef DT_THISPROCNUM
  8. # define DT_THISPROCNUM 0
  9. #endif
  10. #define IN_RANGE(l, addr) \
  11. ((ElfW(Addr)) (addr) >= (l)->l_map_start && (ElfW(Addr)) (addr) < (l)->l_map_end)
  12. #define RELOCATE(l, addr) \
  13. ((typeof(addr)) (IN_RANGE((l), (addr)) ? (ElfW(Addr)) (addr) : \
  14. (ElfW(Addr)) (addr) + (ElfW(Addr)) ((l)->l_addr)))
  15. #ifdef __x86_64__
  16. # include "dl-machine-x86_64.h"
  17. #endif
  18. /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
  19. static inline
  20. void __attribute__ ((unused, always_inline))
  21. elf_get_dynamic_info (struct link_map * l)
  22. {
  23. #if __ELF_NATIVE_CLASS == 32
  24. typedef Elf32_Word d_tag_utype;
  25. #elif __ELF_NATIVE_CLASS == 64
  26. typedef Elf64_Xword d_tag_utype;
  27. #endif
  28. ElfW(Dyn) * dyn = l->l_ld;
  29. if (dyn == NULL)
  30. return;
  31. while (dyn->d_tag != DT_NULL) {
  32. int tag = 0;
  33. if ((d_tag_utype) dyn->d_tag < DT_NUM)
  34. tag = dyn->d_tag;
  35. else if (dyn->d_tag >= DT_LOPROC &&
  36. dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
  37. tag = dyn->d_tag - DT_LOPROC + DT_NUM;
  38. else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
  39. tag = VERSYMIDX (dyn->d_tag);
  40. else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
  41. tag = DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  42. + DT_VERSIONTAGNUM;
  43. else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
  44. tag = DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  45. + DT_VERSIONTAGNUM + DT_EXTRANUM;
  46. else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
  47. tag = DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
  48. + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM;
  49. if (tag)
  50. l->l_info[tag] = dyn;
  51. ++dyn;
  52. }
  53. if (l->l_addr) {
  54. # define ADJUST_DYN_INFO(tag) \
  55. do { \
  56. if (l->l_info[tag] != NULL) { \
  57. l->l_info[tag]->d_un.d_ptr = \
  58. RELOCATE(l, l->l_info[tag]->d_un.d_ptr); \
  59. /* debug("relocate info[%d] = %p\n", \
  60. tag, l->l_info[tag]->d_un.d_ptr); */ \
  61. } \
  62. } while(0);
  63. ADJUST_DYN_INFO (DT_HASH);
  64. ADJUST_DYN_INFO (DT_PLTGOT);
  65. ADJUST_DYN_INFO (DT_STRTAB);
  66. ADJUST_DYN_INFO (DT_SYMTAB);
  67. # if ! ELF_MACHINE_NO_RELA
  68. ADJUST_DYN_INFO (DT_RELA);
  69. # endif
  70. # if ! ELF_MACHINE_NO_REL
  71. ADJUST_DYN_INFO (DT_REL);
  72. # endif
  73. ADJUST_DYN_INFO (DT_JMPREL);
  74. ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
  75. ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
  76. + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
  77. # undef ADJUST_DYN_INFO
  78. }
  79. /* Then a bunch of assertion, we could kind of ignore them */
  80. if (l->l_info[DT_PLTREL] != NULL) {
  81. #if ELF_MACHINE_NO_RELA
  82. assert (l->l_info[DT_PLTREL]->d_un.d_val == DT_REL);
  83. #elif ELF_MACHINE_NO_REL
  84. assert (l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA);
  85. #else
  86. assert (l->l_info[DT_PLTREL]->d_un.d_val == DT_REL
  87. || l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA);
  88. #endif
  89. }
  90. #if ! ELF_MACHINE_NO_RELA
  91. if (l->l_info[DT_RELA] != NULL)
  92. assert (l->l_info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
  93. # endif
  94. # if ! ELF_MACHINE_NO_REL
  95. if (l->l_info[DT_REL] != NULL)
  96. assert (l->l_info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
  97. #endif
  98. }
  99. /* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
  100. These functions are almost identical, so we use cpp magic to avoid
  101. duplicating their code. It cannot be done in a more general function
  102. because we must be able to completely inline. */
  103. /* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
  104. range. Note that according to the ELF spec, this is completely legal!
  105. But conditionally define things so that on machines we know this will
  106. not happen we do something more optimal. */
  107. #ifdef ELF_MACHINE_PLTREL_OVERLAP
  108. /* ELF_MACHINE_PLTREL_OVERLAP is only used for s390, powerpc and sparc.
  109. We will keep it for now */
  110. static void
  111. _elf_dynamic_do_reloc(struct link_map * l, int dt_reloc, int dt_reloc_sz,
  112. void (*do_reloc) (struct link_map *, ElfW(Addr), int))
  113. {
  114. struct { ElfW(Addr) start, size; } ranges[3];
  115. ranges[0].size = ranges[1].size = ranges[2].size = 0;
  116. if (l->l_info[dt_reloc]) {
  117. ranges[0].start = D_PTR (l->l_info[dt_reloc]);
  118. ranges[0].size = l->l_info[dt_reloc_sz]->d_un.d_val;
  119. }
  120. for (int ranges_index = 0; ranges_index < 3; ++ranges_index)
  121. (*do_reloc) (l,
  122. ranges[ranges_index].start,
  123. ranges[ranges_index].size);
  124. }
  125. #else
  126. /* Now this part is for our x86s machines */
  127. static void __attribute__((unused))
  128. _elf_dynamic_do_reloc(struct link_map * l, int dt_reloc, int dt_reloc_sz,
  129. void (*do_reloc) (struct link_map *, ElfW(Addr), int))
  130. {
  131. struct { ElfW(Addr) start, size; } ranges[2];
  132. ranges[0].size = ranges[1].size = 0;
  133. ranges[0].start = ranges[1].start = 0;
  134. if (l->l_info[dt_reloc]) {
  135. ranges[0].start = D_PTR (l->l_info[dt_reloc]);
  136. ranges[0].size = l->l_info[dt_reloc_sz]->d_un.d_val;
  137. }
  138. if (l->l_info[DT_PLTREL]
  139. && l->l_info[DT_PLTREL]->d_un.d_val == dt_reloc) {
  140. ElfW(Addr) start = D_PTR (l->l_info[DT_JMPREL]);
  141. /* This test does not only detect whether the relocation
  142. sections are in the right order, it also checks whether
  143. there is a DT_REL/DT_RELA section. */
  144. if (ranges[0].start + ranges[0].size != start) {
  145. ranges[1].start = start;
  146. ranges[1].size = l->l_info[DT_PLTRELSZ]->d_un.d_val;
  147. } else {
  148. /* Combine processing the sections. */
  149. assert (ranges[0].start + ranges[0].size == start);
  150. ranges[0].size += l->l_info[DT_PLTRELSZ]->d_un.d_val;
  151. }
  152. }
  153. for (int ranges_index = 0; ranges_index < 2; ++ranges_index)
  154. (*do_reloc) (l,
  155. ranges[ranges_index].start,
  156. ranges[ranges_index].size);
  157. }
  158. #endif
  159. #define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, l) \
  160. _elf_dynamic_do_reloc(l, DT_##RELOC, DT_##RELOC##SZ, \
  161. &elf_dynamic_do_##reloc)
  162. #define _ELF_DYNAMIC_REDO_RELOC(RELOC, reloc, l) elf_dynamic_redo_##reloc(l)
  163. #if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
  164. # define _ELF_CHECK_REL 0
  165. #else
  166. # define _ELF_CHECK_REL 1
  167. #endif
  168. #if ! ELF_MACHINE_NO_REL
  169. # include "do-rel.h"
  170. # define ELF_DYNAMIC_DO_REL(l) _ELF_DYNAMIC_DO_RELOC (REL, rel, l)
  171. # define ELF_DYNAMIC_COPY_REL(l1, l2) elf_dynamic_copy_rel(l1, l2)
  172. # define ELF_DYNAMIC_REDO_REL(l) _ELF_DYNAMIC_REDO_RELOC (REL, rel, l)
  173. #else
  174. /* nothing to do */
  175. # define ELF_DYNAMIC_DO_REL(l)
  176. //# define ELF_DYNAMIC_COPY_REL(l1, l2)
  177. # define ELF_DYNAMIC_REDO_REL(l)
  178. #endif
  179. #if ! ELF_MACHINE_NO_RELA
  180. # define DO_RELA
  181. # include "do-rel.h"
  182. # define ELF_DYNAMIC_DO_RELA(l) _ELF_DYNAMIC_DO_RELOC (RELA, rela, l)
  183. //# define ELF_DYNAMIC_COPY_RELA(l1, l2) elf_dynamic_copy_rela(l, l2)
  184. # define ELF_DYNAMIC_REDO_RELA(l) _ELF_DYNAMIC_REDO_RELOC (RELA, rela, l)
  185. #else
  186. /* nothing to do */
  187. # define ELF_DYNAMIC_DO_RELA(l)
  188. //# define ELF_DYNAMIC_COPY_RELA(l1, l2)
  189. # define ELF_DYNAMIC_REDO_RELA(l)
  190. #endif
  191. /* This can't just be an inline function because GCC is too dumb
  192. to inline functions containing inlines themselves. */
  193. # define ELF_DYNAMIC_RELOCATE(l) \
  194. do { \
  195. ELF_DYNAMIC_DO_REL(l); \
  196. ELF_DYNAMIC_DO_RELA(l); \
  197. } while (0)
  198. #if 0
  199. #define ELF_DYNAMIC_COPY(l1, l2) \
  200. do { \
  201. ELF_DYNAMIC_COPY_REL(l1, l2); \
  202. ELF_DYNAMIC_COPY_RELA(l1, l2); \
  203. } while (0)
  204. #endif
  205. # define ELF_REDO_DYNAMIC_RELOCATE(l) \
  206. do { \
  207. ELF_DYNAMIC_REDO_REL(l); \
  208. ELF_DYNAMIC_REDO_RELA(l); \
  209. } while (0)