rel.h 8.1 KB

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