ObjectFileInterface.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
  9. #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
  10. #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
  11. #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
  12. #include "llvm/Object/COFF.h"
  13. #include "llvm/Object/ELFObjectFile.h"
  14. #include "llvm/Object/MachO.h"
  15. #include "llvm/Object/ObjectFile.h"
  16. #include "llvm/Support/Debug.h"
  17. #include <optional>
  18. #define DEBUG_TYPE "orc"
  19. namespace llvm {
  20. namespace orc {
  21. void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
  22. StringRef ObjFileName) {
  23. assert(!I.InitSymbol && "I already has an init symbol");
  24. size_t Counter = 0;
  25. do {
  26. std::string InitSymString;
  27. raw_string_ostream(InitSymString)
  28. << "$." << ObjFileName << ".__inits." << Counter++;
  29. I.InitSymbol = ES.intern(InitSymString);
  30. } while (I.SymbolFlags.count(I.InitSymbol));
  31. I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
  32. }
  33. static Expected<MaterializationUnit::Interface>
  34. getMachOObjectFileSymbolInfo(ExecutionSession &ES,
  35. const object::MachOObjectFile &Obj) {
  36. MaterializationUnit::Interface I;
  37. for (auto &Sym : Obj.symbols()) {
  38. Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
  39. if (!SymFlagsOrErr)
  40. // TODO: Test this error.
  41. return SymFlagsOrErr.takeError();
  42. // Skip symbols not defined in this object file.
  43. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
  44. continue;
  45. // Skip symbols that are not global.
  46. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
  47. continue;
  48. // Skip symbols that have type SF_File.
  49. if (auto SymType = Sym.getType()) {
  50. if (*SymType == object::SymbolRef::ST_File)
  51. continue;
  52. } else
  53. return SymType.takeError();
  54. auto Name = Sym.getName();
  55. if (!Name)
  56. return Name.takeError();
  57. auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
  58. if (!SymFlags)
  59. return SymFlags.takeError();
  60. // Strip the 'exported' flag from MachO linker-private symbols.
  61. if (Name->startswith("l"))
  62. *SymFlags &= ~JITSymbolFlags::Exported;
  63. I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
  64. }
  65. for (auto &Sec : Obj.sections()) {
  66. auto SecType = Obj.getSectionType(Sec);
  67. if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
  68. addInitSymbol(I, ES, Obj.getFileName());
  69. break;
  70. }
  71. auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
  72. auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
  73. if (MachOPlatform::isInitializerSection(SegName, SecName)) {
  74. addInitSymbol(I, ES, Obj.getFileName());
  75. break;
  76. }
  77. }
  78. return I;
  79. }
  80. static Expected<MaterializationUnit::Interface>
  81. getELFObjectFileSymbolInfo(ExecutionSession &ES,
  82. const object::ELFObjectFileBase &Obj) {
  83. MaterializationUnit::Interface I;
  84. for (auto &Sym : Obj.symbols()) {
  85. Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
  86. if (!SymFlagsOrErr)
  87. // TODO: Test this error.
  88. return SymFlagsOrErr.takeError();
  89. // Skip symbols not defined in this object file.
  90. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
  91. continue;
  92. // Skip symbols that are not global.
  93. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
  94. continue;
  95. // Skip symbols that have type SF_File.
  96. if (auto SymType = Sym.getType()) {
  97. if (*SymType == object::SymbolRef::ST_File)
  98. continue;
  99. } else
  100. return SymType.takeError();
  101. auto Name = Sym.getName();
  102. if (!Name)
  103. return Name.takeError();
  104. auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
  105. if (!SymFlags)
  106. return SymFlags.takeError();
  107. // ELF STB_GNU_UNIQUE should map to Weak for ORC.
  108. if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
  109. *SymFlags |= JITSymbolFlags::Weak;
  110. I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
  111. }
  112. SymbolStringPtr InitSymbol;
  113. for (auto &Sec : Obj.sections()) {
  114. if (auto SecName = Sec.getName()) {
  115. if (ELFNixPlatform::isInitializerSection(*SecName)) {
  116. addInitSymbol(I, ES, Obj.getFileName());
  117. break;
  118. }
  119. }
  120. }
  121. return I;
  122. }
  123. static Expected<MaterializationUnit::Interface>
  124. getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
  125. const object::COFFObjectFile &Obj) {
  126. MaterializationUnit::Interface I;
  127. std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
  128. Obj.getNumberOfSections() + 1);
  129. for (auto &Sym : Obj.symbols()) {
  130. Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
  131. if (!SymFlagsOrErr)
  132. // TODO: Test this error.
  133. return SymFlagsOrErr.takeError();
  134. // Handle comdat symbols
  135. auto COFFSym = Obj.getCOFFSymbol(Sym);
  136. bool IsWeak = false;
  137. if (auto *Def = COFFSym.getSectionDefinition()) {
  138. auto Sec = Obj.getSection(COFFSym.getSectionNumber());
  139. if (!Sec)
  140. return Sec.takeError();
  141. if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
  142. Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
  143. ComdatDefs[COFFSym.getSectionNumber()] = *Def;
  144. continue;
  145. }
  146. }
  147. if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
  148. ComdatDefs[COFFSym.getSectionNumber()]) {
  149. auto Def = ComdatDefs[COFFSym.getSectionNumber()];
  150. if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
  151. IsWeak = true;
  152. }
  153. ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
  154. } else {
  155. // Skip symbols not defined in this object file.
  156. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
  157. continue;
  158. }
  159. // Skip symbols that are not global.
  160. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
  161. continue;
  162. // Skip symbols that have type SF_File.
  163. if (auto SymType = Sym.getType()) {
  164. if (*SymType == object::SymbolRef::ST_File)
  165. continue;
  166. } else
  167. return SymType.takeError();
  168. auto Name = Sym.getName();
  169. if (!Name)
  170. return Name.takeError();
  171. auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
  172. if (!SymFlags)
  173. return SymFlags.takeError();
  174. *SymFlags |= JITSymbolFlags::Exported;
  175. // Weak external is always a function
  176. if (COFFSym.isWeakExternal())
  177. *SymFlags |= JITSymbolFlags::Callable;
  178. if (IsWeak)
  179. *SymFlags |= JITSymbolFlags::Weak;
  180. I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
  181. }
  182. SymbolStringPtr InitSymbol;
  183. for (auto &Sec : Obj.sections()) {
  184. if (auto SecName = Sec.getName()) {
  185. if (COFFPlatform::isInitializerSection(*SecName)) {
  186. addInitSymbol(I, ES, Obj.getFileName());
  187. break;
  188. }
  189. } else
  190. return SecName.takeError();
  191. }
  192. return I;
  193. }
  194. Expected<MaterializationUnit::Interface>
  195. getGenericObjectFileSymbolInfo(ExecutionSession &ES,
  196. const object::ObjectFile &Obj) {
  197. MaterializationUnit::Interface I;
  198. for (auto &Sym : Obj.symbols()) {
  199. Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
  200. if (!SymFlagsOrErr)
  201. // TODO: Test this error.
  202. return SymFlagsOrErr.takeError();
  203. // Skip symbols not defined in this object file.
  204. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
  205. continue;
  206. // Skip symbols that are not global.
  207. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
  208. continue;
  209. // Skip symbols that have type SF_File.
  210. if (auto SymType = Sym.getType()) {
  211. if (*SymType == object::SymbolRef::ST_File)
  212. continue;
  213. } else
  214. return SymType.takeError();
  215. auto Name = Sym.getName();
  216. if (!Name)
  217. return Name.takeError();
  218. auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
  219. if (!SymFlags)
  220. return SymFlags.takeError();
  221. I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
  222. }
  223. return I;
  224. }
  225. Expected<MaterializationUnit::Interface>
  226. getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
  227. auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
  228. if (!Obj)
  229. return Obj.takeError();
  230. if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
  231. return getMachOObjectFileSymbolInfo(ES, *MachOObj);
  232. else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
  233. return getELFObjectFileSymbolInfo(ES, *ELFObj);
  234. else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
  235. return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
  236. return getGenericObjectFileSymbolInfo(ES, **Obj);
  237. }
  238. bool hasInitializerSection(jitlink::LinkGraph &G) {
  239. bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
  240. bool IsElf = G.getTargetTriple().isOSBinFormatELF();
  241. if (!IsMachO && !IsElf)
  242. return false;
  243. for (auto &Sec : G.sections()) {
  244. if (IsMachO && std::apply(MachOPlatform::isInitializerSection,
  245. Sec.getName().split(",")))
  246. return true;
  247. if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName()))
  248. return true;
  249. }
  250. return false;
  251. }
  252. } // End namespace orc.
  253. } // End namespace llvm.