Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.3 KiB

  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/ObjectFile.h"
  19. #include "llvm/Support/Debug.h"
  20. #include "llvm/Support/ELF.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. namespace llvm {
  23. namespace object {
  24. struct RelocToApply {
  25. // The computed value after applying the relevant relocations.
  26. int64_t Value;
  27. // The width of the value; how many bytes to touch when applying the
  28. // relocation.
  29. char Width;
  30. RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {}
  31. RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
  32. RelocToApply() : Value(0), Width(0) {}
  33. };
  34. /// @brief Base class for object file relocation visitors.
  35. class RelocVisitor {
  36. public:
  37. explicit RelocVisitor(StringRef FileFormat)
  38. : FileFormat(FileFormat), HasError(false) {}
  39. // TODO: Should handle multiple applied relocations via either passing in the
  40. // previously computed value or just count paired relocations as a single
  41. // visit.
  42. RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
  43. uint64_t Value = 0) {
  44. if (FileFormat == "ELF64-x86-64") {
  45. switch (RelocType) {
  46. case llvm::ELF::R_X86_64_NONE:
  47. return visitELF_X86_64_NONE(R);
  48. case llvm::ELF::R_X86_64_64:
  49. return visitELF_X86_64_64(R, Value);
  50. case llvm::ELF::R_X86_64_PC32:
  51. return visitELF_X86_64_PC32(R, Value, SecAddr);
  52. case llvm::ELF::R_X86_64_32:
  53. return visitELF_X86_64_32(R, Value);
  54. case llvm::ELF::R_X86_64_32S:
  55. return visitELF_X86_64_32S(R, Value);
  56. default:
  57. HasError = true;
  58. return RelocToApply();
  59. }
  60. } else if (FileFormat == "ELF32-i386") {
  61. switch (RelocType) {
  62. case llvm::ELF::R_386_NONE:
  63. return visitELF_386_NONE(R);
  64. case llvm::ELF::R_386_32:
  65. return visitELF_386_32(R, Value);
  66. case llvm::ELF::R_386_PC32:
  67. return visitELF_386_PC32(R, Value, SecAddr);
  68. default:
  69. HasError = true;
  70. return RelocToApply();
  71. }
  72. } else if (FileFormat == "ELF64-ppc64") {
  73. switch (RelocType) {
  74. case llvm::ELF::R_PPC64_ADDR32:
  75. return visitELF_PPC64_ADDR32(R, Value);
  76. default:
  77. HasError = true;
  78. return RelocToApply();
  79. }
  80. } else if (FileFormat == "ELF32-mips") {
  81. switch (RelocType) {
  82. case llvm::ELF::R_MIPS_32:
  83. return visitELF_MIPS_32(R, Value);
  84. default:
  85. HasError = true;
  86. return RelocToApply();
  87. }
  88. } else if (FileFormat == "ELF64-aarch64") {
  89. switch (RelocType) {
  90. case llvm::ELF::R_AARCH64_ABS32:
  91. return visitELF_AARCH64_ABS32(R, Value);
  92. case llvm::ELF::R_AARCH64_ABS64:
  93. return visitELF_AARCH64_ABS64(R, Value);
  94. default:
  95. HasError = true;
  96. return RelocToApply();
  97. }
  98. }
  99. HasError = true;
  100. return RelocToApply();
  101. }
  102. bool error() { return HasError; }
  103. private:
  104. StringRef FileFormat;
  105. bool HasError;
  106. /// Operations
  107. /// 386-ELF
  108. RelocToApply visitELF_386_NONE(RelocationRef R) {
  109. return RelocToApply(0, 0);
  110. }
  111. // Ideally the Addend here will be the addend in the data for
  112. // the relocation. It's not actually the case for Rel relocations.
  113. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
  114. int64_t Addend;
  115. R.getAdditionalInfo(Addend);
  116. return RelocToApply(Value + Addend, 4);
  117. }
  118. RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
  119. uint64_t SecAddr) {
  120. int64_t Addend;
  121. R.getAdditionalInfo(Addend);
  122. uint64_t Address;
  123. R.getAddress(Address);
  124. return RelocToApply(Value + Addend - Address, 4);
  125. }
  126. /// X86-64 ELF
  127. RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
  128. return RelocToApply(0, 0);
  129. }
  130. RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
  131. int64_t Addend;
  132. R.getAdditionalInfo(Addend);
  133. return RelocToApply(Value + Addend, 8);
  134. }
  135. RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
  136. uint64_t SecAddr) {
  137. int64_t Addend;
  138. R.getAdditionalInfo(Addend);
  139. uint64_t Address;
  140. R.getAddress(Address);
  141. return RelocToApply(Value + Addend - Address, 4);
  142. }
  143. RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
  144. int64_t Addend;
  145. R.getAdditionalInfo(Addend);
  146. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  147. return RelocToApply(Res, 4);
  148. }
  149. RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
  150. int64_t Addend;
  151. R.getAdditionalInfo(Addend);
  152. int32_t Res = (Value + Addend) & 0xFFFFFFFF;
  153. return RelocToApply(Res, 4);
  154. }
  155. /// PPC64 ELF
  156. RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
  157. int64_t Addend;
  158. R.getAdditionalInfo(Addend);
  159. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  160. return RelocToApply(Res, 4);
  161. }
  162. /// MIPS ELF
  163. RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
  164. int64_t Addend;
  165. R.getAdditionalInfo(Addend);
  166. uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
  167. return RelocToApply(Res, 4);
  168. }
  169. // AArch64 ELF
  170. RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
  171. int64_t Addend;
  172. R.getAdditionalInfo(Addend);
  173. int64_t Res = Value + Addend;
  174. // Overflow check allows for both signed and unsigned interpretation.
  175. if (Res < INT32_MIN || Res > UINT32_MAX)
  176. HasError = true;
  177. return RelocToApply(static_cast<uint32_t>(Res), 4);
  178. }
  179. RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
  180. int64_t Addend;
  181. R.getAdditionalInfo(Addend);
  182. return RelocToApply(Value + Addend, 8);
  183. }
  184. };
  185. }
  186. }
  187. #endif