RelocVisitor.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. //===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file provides a wrapper around all the different types of relocations
  11. // in different file formats, such that a client can handle them in a unified
  12. // manner by only implementing a minimal number of functions.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #ifndef LLVM_OBJECT_RELOCVISITOR_H
  16. #define LLVM_OBJECT_RELOCVISITOR_H
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/Object/COFF.h"
  19. #include "llvm/Object/ELFObjectFile.h"
  20. #include "llvm/Object/MachO.h"
  21. #include "llvm/Object/ObjectFile.h"
  22. #include "llvm/Support/Debug.h"
  23. #include "llvm/Support/ELF.h"
  24. #include "llvm/Support/MachO.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. namespace llvm {
  27. namespace object {
  28. struct RelocToApply {
  29. // The computed value after applying the relevant relocations.
  30. int64_t Value;
  31. // The width of the value; how many bytes to touch when applying the
  32. // relocation.
  33. char Width;
  34. RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
  35. RelocToApply() : Value(0), Width(0) {}
  36. };
  37. /// @brief Base class for object file relocation visitors.
  38. class RelocVisitor {
  39. public:
  40. explicit RelocVisitor(const ObjectFile &Obj)
  41. : ObjToVisit(Obj), HasError(false) {}
  42. // TODO: Should handle multiple applied relocations via either passing in the
  43. // previously computed value or just count paired relocations as a single
  44. // visit.
  45. RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
  46. if (isa<ELFObjectFileBase>(ObjToVisit))
  47. return visitELF(RelocType, R, Value);
  48. if (isa<COFFObjectFile>(ObjToVisit))
  49. return visitCOFF(RelocType, R, Value);
  50. if (isa<MachOObjectFile>(ObjToVisit))
  51. return visitMachO(RelocType, R, Value);
  52. HasError = true;
  53. return RelocToApply();
  54. }
  55. bool error() { return HasError; }
  56. private:
  57. const ObjectFile &ObjToVisit;
  58. bool HasError;
  59. RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
  60. if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
  61. switch (ObjToVisit.getArch()) {
  62. case Triple::x86_64:
  63. switch (RelocType) {
  64. case llvm::ELF::R_X86_64_NONE:
  65. return visitELF_X86_64_NONE(R);
  66. case llvm::ELF::R_X86_64_64:
  67. return visitELF_X86_64_64(R, Value);
  68. case llvm::ELF::R_X86_64_PC32:
  69. return visitELF_X86_64_PC32(R, Value);
  70. case llvm::ELF::R_X86_64_32:
  71. return visitELF_X86_64_32(R, Value);
  72. case llvm::ELF::R_X86_64_32S:
  73. return visitELF_X86_64_32S(R, Value);
  74. default:
  75. HasError = true;
  76. return RelocToApply();
  77. }
  78. case Triple::aarch64:
  79. switch (RelocType) {
  80. case llvm::ELF::R_AARCH64_ABS32:
  81. return visitELF_AARCH64_ABS32(R, Value);
  82. case llvm::ELF::R_AARCH64_ABS64:
  83. return visitELF_AARCH64_ABS64(R, Value);
  84. default:
  85. HasError = true;
  86. return RelocToApply();
  87. }
  88. case Triple::mips64el:
  89. case Triple::mips64:
  90. switch (RelocType) {
  91. case llvm::ELF::R_MIPS_32:
  92. return visitELF_MIPS64_32(R, Value);
  93. case llvm::ELF::R_MIPS_64:
  94. return visitELF_MIPS64_64(R, Value);
  95. default:
  96. HasError = true;
  97. return RelocToApply();
  98. }
  99. case Triple::ppc64le:
  100. case Triple::ppc64:
  101. switch (RelocType) {
  102. case llvm::ELF::R_PPC64_ADDR32:
  103. return visitELF_PPC64_ADDR32(R, Value);
  104. case llvm::ELF::R_PPC64_ADDR64:
  105. return visitELF_PPC64_ADDR64(R, Value);
  106. default:
  107. HasError = true;
  108. return RelocToApply();
  109. }
  110. case Triple::systemz:
  111. switch (RelocType) {
  112. case llvm::ELF::R_390_32:
  113. return visitELF_390_32(R, Value);
  114. case llvm::ELF::R_390_64:
  115. return visitELF_390_64(R, Value);
  116. default:
  117. HasError = true;
  118. return RelocToApply();
  119. }
  120. case Triple::sparcv9:
  121. switch (RelocType) {
  122. case llvm::ELF::R_SPARC_32:
  123. case llvm::ELF::R_SPARC_UA32:
  124. return visitELF_SPARCV9_32(R, Value);
  125. case llvm::ELF::R_SPARC_64:
  126. case llvm::ELF::R_SPARC_UA64:
  127. return visitELF_SPARCV9_64(R, Value);
  128. default:
  129. HasError = true;
  130. return RelocToApply();
  131. }
  132. default:
  133. HasError = true;
  134. return RelocToApply();
  135. }
  136. } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
  137. switch (ObjToVisit.getArch()) {
  138. case Triple::x86:
  139. switch (RelocType) {
  140. case llvm::ELF::R_386_NONE:
  141. return visitELF_386_NONE(R);
  142. case llvm::ELF::R_386_32:
  143. return visitELF_386_32(R, Value);
  144. case llvm::ELF::R_386_PC32:
  145. return visitELF_386_PC32(R, Value);
  146. default:
  147. HasError = true;
  148. return RelocToApply();
  149. }
  150. case Triple::ppc:
  151. switch (RelocType) {
  152. case llvm::ELF::R_PPC_ADDR32:
  153. return visitELF_PPC_ADDR32(R, Value);
  154. default:
  155. HasError = true;
  156. return RelocToApply();
  157. }
  158. case Triple::arm:
  159. case Triple::armeb:
  160. switch (RelocType) {
  161. default:
  162. HasError = true;
  163. return RelocToApply();
  164. case llvm::ELF::R_ARM_ABS32:
  165. return visitELF_ARM_ABS32(R, Value);
  166. }
  167. case Triple::mipsel:
  168. case Triple::mips:
  169. switch (RelocType) {
  170. case llvm::ELF::R_MIPS_32:
  171. return visitELF_MIPS_32(R, Value);
  172. default:
  173. HasError = true;
  174. return RelocToApply();
  175. }
  176. case Triple::sparc:
  177. switch (RelocType) {
  178. case llvm::ELF::R_SPARC_32:
  179. case llvm::ELF::R_SPARC_UA32:
  180. return visitELF_SPARC_32(R, Value);
  181. default:
  182. HasError = true;
  183. return RelocToApply();
  184. }
  185. default:
  186. HasError = true;
  187. return RelocToApply();
  188. }
  189. } else {
  190. report_fatal_error("Invalid word size in object file");
  191. }
  192. }
  193. RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
  194. switch (ObjToVisit.getArch()) {
  195. case Triple::x86:
  196. switch (RelocType) {
  197. case COFF::IMAGE_REL_I386_SECREL:
  198. return visitCOFF_I386_SECREL(R, Value);
  199. case COFF::IMAGE_REL_I386_DIR32:
  200. return visitCOFF_I386_DIR32(R, Value);
  201. }
  202. break;
  203. case Triple::x86_64:
  204. switch (RelocType) {
  205. case COFF::IMAGE_REL_AMD64_SECREL:
  206. return visitCOFF_AMD64_SECREL(R, Value);
  207. case COFF::IMAGE_REL_AMD64_ADDR64:
  208. return visitCOFF_AMD64_ADDR64(R, Value);
  209. }
  210. break;
  211. }
  212. HasError = true;
  213. return RelocToApply();
  214. }
  215. RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
  216. switch (ObjToVisit.getArch()) {
  217. default: break;
  218. case Triple::x86_64:
  219. switch (RelocType) {
  220. default: break;
  221. case MachO::X86_64_RELOC_UNSIGNED:
  222. return visitMACHO_X86_64_UNSIGNED(R, Value);
  223. }
  224. }
  225. HasError = true;
  226. return RelocToApply();
  227. }
  228. int64_t getELFAddend(RelocationRef R) {
  229. ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
  230. if (std::error_code EC = AddendOrErr.getError())
  231. report_fatal_error(EC.message());
  232. return *AddendOrErr;
  233. }
  234. uint8_t getLengthMachO64(RelocationRef R) {
  235. const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
  236. return Obj->getRelocationLength(R.getRawDataRefImpl());
  237. }
  238. /// Operations
  239. /// 386-ELF
  240. RelocToApply visitELF_386_NONE(RelocationRef R) {
  241. return RelocToApply(0, 0);
  242. }
  243. // Ideally the Addend here will be the addend in the data for
  244. // the relocation. It's not actually the case for Rel relocations.
  245. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
  246. return RelocToApply(Value, 4);
  247. }
  248. RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
  249. uint64_t Address = R.getOffset();
  250. return RelocToApply(Value - Address, 4);
  251. }
  252. /// X86-64 ELF
  253. RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
  254. return RelocToApply(0, 0);
  255. }
  256. RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
  257. int64_t Addend = getELFAddend(R);
  258. return RelocToApply(Value + Addend, 8);
  259. }
  260. RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
  261. int64_t Addend = getELFAddend(R);
  262. uint64_t Address = R.getOffset();
  263. return RelocToApply(Value + Addend - Address, 4);
  264. }
  265. RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
  266. int64_t Addend = getELFAddend(R);
  267. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  268. return RelocToApply(Res, 4);
  269. }
  270. RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
  271. int64_t Addend = getELFAddend(R);
  272. int32_t Res = (Value + Addend) & 0xFFFFFFFF;
  273. return RelocToApply(Res, 4);
  274. }
  275. /// PPC64 ELF
  276. RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
  277. int64_t Addend = getELFAddend(R);
  278. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  279. return RelocToApply(Res, 4);
  280. }
  281. RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
  282. int64_t Addend = getELFAddend(R);
  283. return RelocToApply(Value + Addend, 8);
  284. }
  285. /// PPC32 ELF
  286. RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
  287. int64_t Addend = getELFAddend(R);
  288. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  289. return RelocToApply(Res, 4);
  290. }
  291. /// MIPS ELF
  292. RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
  293. uint32_t Res = Value & 0xFFFFFFFF;
  294. return RelocToApply(Res, 4);
  295. }
  296. /// MIPS64 ELF
  297. RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
  298. int64_t Addend = getELFAddend(R);
  299. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  300. return RelocToApply(Res, 4);
  301. }
  302. RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
  303. int64_t Addend = getELFAddend(R);
  304. uint64_t Res = (Value + Addend);
  305. return RelocToApply(Res, 8);
  306. }
  307. // AArch64 ELF
  308. RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
  309. int64_t Addend = getELFAddend(R);
  310. int64_t Res = Value + Addend;
  311. // Overflow check allows for both signed and unsigned interpretation.
  312. if (Res < INT32_MIN || Res > UINT32_MAX)
  313. HasError = true;
  314. return RelocToApply(static_cast<uint32_t>(Res), 4);
  315. }
  316. RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
  317. int64_t Addend = getELFAddend(R);
  318. return RelocToApply(Value + Addend, 8);
  319. }
  320. // SystemZ ELF
  321. RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
  322. int64_t Addend = getELFAddend(R);
  323. int64_t Res = Value + Addend;
  324. // Overflow check allows for both signed and unsigned interpretation.
  325. if (Res < INT32_MIN || Res > UINT32_MAX)
  326. HasError = true;
  327. return RelocToApply(static_cast<uint32_t>(Res), 4);
  328. }
  329. RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
  330. int64_t Addend = getELFAddend(R);
  331. return RelocToApply(Value + Addend, 8);
  332. }
  333. RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
  334. int32_t Addend = getELFAddend(R);
  335. return RelocToApply(Value + Addend, 4);
  336. }
  337. RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
  338. int32_t Addend = getELFAddend(R);
  339. return RelocToApply(Value + Addend, 4);
  340. }
  341. RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
  342. int64_t Addend = getELFAddend(R);
  343. return RelocToApply(Value + Addend, 8);
  344. }
  345. RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
  346. int64_t Res = Value;
  347. // Overflow check allows for both signed and unsigned interpretation.
  348. if (Res < INT32_MIN || Res > UINT32_MAX)
  349. HasError = true;
  350. return RelocToApply(static_cast<uint32_t>(Res), 4);
  351. }
  352. /// I386 COFF
  353. RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
  354. return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
  355. }
  356. RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
  357. return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
  358. }
  359. /// AMD64 COFF
  360. RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
  361. return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
  362. }
  363. RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
  364. return RelocToApply(Value, /*Width=*/8);
  365. }
  366. // X86_64 MachO
  367. RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
  368. uint8_t Length = getLengthMachO64(R);
  369. Length = 1<<Length;
  370. return RelocToApply(Value, Length);
  371. }
  372. };
  373. }
  374. }
  375. #endif