Object.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. //===- Object.cpp - C bindings to the object file library--------*- C++ -*-===//
  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. //
  9. // This file defines the C bindings to the file-format-independent object
  10. // library.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm-c/Object.h"
  14. #include "llvm/ADT/SmallVector.h"
  15. #include "llvm/IR/LLVMContext.h"
  16. #include "llvm/Object/ObjectFile.h"
  17. using namespace llvm;
  18. using namespace object;
  19. inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) {
  20. return reinterpret_cast<OwningBinary<ObjectFile> *>(OF);
  21. }
  22. inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) {
  23. return reinterpret_cast<LLVMObjectFileRef>(
  24. const_cast<OwningBinary<ObjectFile> *>(OF));
  25. }
  26. inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
  27. return reinterpret_cast<section_iterator*>(SI);
  28. }
  29. inline LLVMSectionIteratorRef
  30. wrap(const section_iterator *SI) {
  31. return reinterpret_cast<LLVMSectionIteratorRef>
  32. (const_cast<section_iterator*>(SI));
  33. }
  34. inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) {
  35. return reinterpret_cast<symbol_iterator*>(SI);
  36. }
  37. inline LLVMSymbolIteratorRef
  38. wrap(const symbol_iterator *SI) {
  39. return reinterpret_cast<LLVMSymbolIteratorRef>
  40. (const_cast<symbol_iterator*>(SI));
  41. }
  42. inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) {
  43. return reinterpret_cast<relocation_iterator*>(SI);
  44. }
  45. inline LLVMRelocationIteratorRef
  46. wrap(const relocation_iterator *SI) {
  47. return reinterpret_cast<LLVMRelocationIteratorRef>
  48. (const_cast<relocation_iterator*>(SI));
  49. }
  50. /*--.. Operations on binary files ..........................................--*/
  51. LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf,
  52. LLVMContextRef Context,
  53. char **ErrorMessage) {
  54. auto maybeContext = Context ? unwrap(Context) : nullptr;
  55. Expected<std::unique_ptr<Binary>> ObjOrErr(
  56. createBinary(unwrap(MemBuf)->getMemBufferRef(), maybeContext));
  57. if (!ObjOrErr) {
  58. *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str());
  59. return nullptr;
  60. }
  61. return wrap(ObjOrErr.get().release());
  62. }
  63. LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) {
  64. auto Buf = unwrap(BR)->getMemoryBufferRef();
  65. return wrap(llvm::MemoryBuffer::getMemBuffer(
  66. Buf.getBuffer(), Buf.getBufferIdentifier(),
  67. /*RequiresNullTerminator*/false).release());
  68. }
  69. void LLVMDisposeBinary(LLVMBinaryRef BR) {
  70. delete unwrap(BR);
  71. }
  72. LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) {
  73. class BinaryTypeMapper final : public Binary {
  74. public:
  75. static LLVMBinaryType mapBinaryTypeToLLVMBinaryType(unsigned Kind) {
  76. switch (Kind) {
  77. case ID_Archive:
  78. return LLVMBinaryTypeArchive;
  79. case ID_MachOUniversalBinary:
  80. return LLVMBinaryTypeMachOUniversalBinary;
  81. case ID_COFFImportFile:
  82. return LLVMBinaryTypeCOFFImportFile;
  83. case ID_IR:
  84. return LLVMBinaryTypeIR;
  85. case ID_WinRes:
  86. return LLVMBinaryTypeWinRes;
  87. case ID_COFF:
  88. return LLVMBinaryTypeCOFF;
  89. case ID_ELF32L:
  90. return LLVMBinaryTypeELF32L;
  91. case ID_ELF32B:
  92. return LLVMBinaryTypeELF32B;
  93. case ID_ELF64L:
  94. return LLVMBinaryTypeELF64L;
  95. case ID_ELF64B:
  96. return LLVMBinaryTypeELF64B;
  97. case ID_MachO32L:
  98. return LLVMBinaryTypeMachO32L;
  99. case ID_MachO32B:
  100. return LLVMBinaryTypeMachO32B;
  101. case ID_MachO64L:
  102. return LLVMBinaryTypeMachO64L;
  103. case ID_MachO64B:
  104. return LLVMBinaryTypeMachO64B;
  105. case ID_Wasm:
  106. return LLVMBinaryTypeWasm;
  107. case ID_StartObjects:
  108. case ID_EndObjects:
  109. llvm_unreachable("Marker types are not valid binary kinds!");
  110. default:
  111. llvm_unreachable("Unknown binary kind!");
  112. }
  113. }
  114. };
  115. return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR)->getType());
  116. }
  117. LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) {
  118. auto OF = cast<ObjectFile>(unwrap(BR));
  119. auto sections = OF->sections();
  120. if (sections.begin() == sections.end())
  121. return nullptr;
  122. return wrap(new section_iterator(sections.begin()));
  123. }
  124. LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
  125. LLVMSectionIteratorRef SI) {
  126. auto OF = cast<ObjectFile>(unwrap(BR));
  127. return (*unwrap(SI) == OF->section_end()) ? 1 : 0;
  128. }
  129. LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) {
  130. auto OF = cast<ObjectFile>(unwrap(BR));
  131. auto symbols = OF->symbols();
  132. if (symbols.begin() == symbols.end())
  133. return nullptr;
  134. return wrap(new symbol_iterator(symbols.begin()));
  135. }
  136. LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,
  137. LLVMSymbolIteratorRef SI) {
  138. auto OF = cast<ObjectFile>(unwrap(BR));
  139. return (*unwrap(SI) == OF->symbol_end()) ? 1 : 0;
  140. }
  141. // ObjectFile creation
  142. LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {
  143. std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf));
  144. Expected<std::unique_ptr<ObjectFile>> ObjOrErr(
  145. ObjectFile::createObjectFile(Buf->getMemBufferRef()));
  146. std::unique_ptr<ObjectFile> Obj;
  147. if (!ObjOrErr) {
  148. // TODO: Actually report errors helpfully.
  149. consumeError(ObjOrErr.takeError());
  150. return nullptr;
  151. }
  152. auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf));
  153. return wrap(Ret);
  154. }
  155. void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
  156. delete unwrap(ObjectFile);
  157. }
  158. // ObjectFile Section iterators
  159. LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) {
  160. OwningBinary<ObjectFile> *OB = unwrap(OF);
  161. section_iterator SI = OB->getBinary()->section_begin();
  162. return wrap(new section_iterator(SI));
  163. }
  164. void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
  165. delete unwrap(SI);
  166. }
  167. LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF,
  168. LLVMSectionIteratorRef SI) {
  169. OwningBinary<ObjectFile> *OB = unwrap(OF);
  170. return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0;
  171. }
  172. void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
  173. ++(*unwrap(SI));
  174. }
  175. void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
  176. LLVMSymbolIteratorRef Sym) {
  177. Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection();
  178. if (!SecOrErr) {
  179. std::string Buf;
  180. raw_string_ostream OS(Buf);
  181. logAllUnhandledErrors(SecOrErr.takeError(), OS);
  182. OS.flush();
  183. report_fatal_error(Buf);
  184. }
  185. *unwrap(Sect) = *SecOrErr;
  186. }
  187. // ObjectFile Symbol iterators
  188. LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) {
  189. OwningBinary<ObjectFile> *OB = unwrap(OF);
  190. symbol_iterator SI = OB->getBinary()->symbol_begin();
  191. return wrap(new symbol_iterator(SI));
  192. }
  193. void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {
  194. delete unwrap(SI);
  195. }
  196. LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF,
  197. LLVMSymbolIteratorRef SI) {
  198. OwningBinary<ObjectFile> *OB = unwrap(OF);
  199. return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0;
  200. }
  201. void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {
  202. ++(*unwrap(SI));
  203. }
  204. // SectionRef accessors
  205. const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
  206. StringRef ret;
  207. if (std::error_code ec = (*unwrap(SI))->getName(ret))
  208. report_fatal_error(ec.message());
  209. return ret.data();
  210. }
  211. uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
  212. return (*unwrap(SI))->getSize();
  213. }
  214. const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
  215. StringRef ret;
  216. if (std::error_code ec = (*unwrap(SI))->getContents(ret))
  217. report_fatal_error(ec.message());
  218. return ret.data();
  219. }
  220. uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {
  221. return (*unwrap(SI))->getAddress();
  222. }
  223. LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
  224. LLVMSymbolIteratorRef Sym) {
  225. return (*unwrap(SI))->containsSymbol(**unwrap(Sym));
  226. }
  227. // Section Relocation iterators
  228. LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
  229. relocation_iterator SI = (*unwrap(Section))->relocation_begin();
  230. return wrap(new relocation_iterator(SI));
  231. }
  232. void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {
  233. delete unwrap(SI);
  234. }
  235. LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
  236. LLVMRelocationIteratorRef SI) {
  237. return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0;
  238. }
  239. void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {
  240. ++(*unwrap(SI));
  241. }
  242. // SymbolRef accessors
  243. const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
  244. Expected<StringRef> Ret = (*unwrap(SI))->getName();
  245. if (!Ret) {
  246. std::string Buf;
  247. raw_string_ostream OS(Buf);
  248. logAllUnhandledErrors(Ret.takeError(), OS);
  249. OS.flush();
  250. report_fatal_error(Buf);
  251. }
  252. return Ret->data();
  253. }
  254. uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
  255. Expected<uint64_t> Ret = (*unwrap(SI))->getAddress();
  256. if (!Ret) {
  257. std::string Buf;
  258. raw_string_ostream OS(Buf);
  259. logAllUnhandledErrors(Ret.takeError(), OS);
  260. OS.flush();
  261. report_fatal_error(Buf);
  262. }
  263. return *Ret;
  264. }
  265. uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {
  266. return (*unwrap(SI))->getCommonSize();
  267. }
  268. // RelocationRef accessors
  269. uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {
  270. return (*unwrap(RI))->getOffset();
  271. }
  272. LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
  273. symbol_iterator ret = (*unwrap(RI))->getSymbol();
  274. return wrap(new symbol_iterator(ret));
  275. }
  276. uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
  277. return (*unwrap(RI))->getType();
  278. }
  279. // NOTE: Caller takes ownership of returned string.
  280. const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
  281. SmallVector<char, 0> ret;
  282. (*unwrap(RI))->getTypeName(ret);
  283. char *str = static_cast<char*>(safe_malloc(ret.size()));
  284. llvm::copy(ret, str);
  285. return str;
  286. }
  287. // NOTE: Caller takes ownership of returned string.
  288. const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
  289. return strdup("");
  290. }