rel.h 8.4 KB

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