xref: /llvm-project/llvm/lib/Object/IRObjectFile.cpp (revision e72c195fdcbe03ce1f728689e11716ec46a258ba)
1 //===- IRObjectFile.cpp - IR object file implementation ---------*- 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 // Part of the IRObjectFile class implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Object/IRObjectFile.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/DenseMapInfo.h"
16 #include "llvm/ADT/PointerUnion.h"
17 #include "llvm/BinaryFormat/Magic.h"
18 #include "llvm/Bitcode/BitcodeReader.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Object/ObjectFile.h"
21 using namespace llvm;
22 using namespace object;
23 
24 namespace llvm {
25 class LLVMContext;
26 class raw_ostream;
27 } // namespace llvm
28 
29 IRObjectFile::IRObjectFile(MemoryBufferRef Object,
30                            std::vector<std::unique_ptr<Module>> Mods)
31     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
32   for (auto &M : this->Mods)
33     SymTab.addModule(M.get());
34 }
35 
36 IRObjectFile::~IRObjectFile() = default;
37 
38 static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
39   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
40 }
41 
42 void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
43   Symb.p += sizeof(ModuleSymbolTable::Symbol);
44 }
45 
46 Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
47   SymTab.printSymbolName(OS, getSym(Symb));
48   return Error::success();
49 }
50 
51 Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
52   return SymTab.getSymbolFlags(getSym(Symb));
53 }
54 
55 basic_symbol_iterator IRObjectFile::symbol_begin() const {
56   DataRefImpl Ret;
57   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
58   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
59 }
60 
61 basic_symbol_iterator IRObjectFile::symbol_end() const {
62   DataRefImpl Ret;
63   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
64                                       SymTab.symbols().size());
65   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
66 }
67 
68 StringRef IRObjectFile::getTargetTriple() const {
69   // Each module must have the same target triple, so we arbitrarily access the
70   // first one.
71   return Mods[0]->getTargetTriple();
72 }
73 
74 Expected<MemoryBufferRef>
75 IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
76   for (const SectionRef &Sec : Obj.sections()) {
77     if (Sec.isBitcode()) {
78       Expected<StringRef> Contents = Sec.getContents();
79       if (!Contents)
80         return Contents.takeError();
81       if (Contents->size() <= 1)
82         return errorCodeToError(object_error::bitcode_section_not_found);
83       return MemoryBufferRef(*Contents, Obj.getFileName());
84     }
85   }
86 
87   return errorCodeToError(object_error::bitcode_section_not_found);
88 }
89 
90 Expected<MemoryBufferRef>
91 IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
92   file_magic Type = identify_magic(Object.getBuffer());
93   switch (Type) {
94   case file_magic::bitcode:
95     return Object;
96   case file_magic::elf_relocatable:
97   case file_magic::macho_object:
98   case file_magic::wasm_object:
99   case file_magic::coff_object: {
100     Expected<std::unique_ptr<ObjectFile>> ObjFile =
101         ObjectFile::createObjectFile(Object, Type);
102     if (!ObjFile)
103       return ObjFile.takeError();
104     return findBitcodeInObject(*ObjFile->get());
105   }
106   default:
107     return errorCodeToError(object_error::invalid_file_type);
108   }
109 }
110 
111 Expected<std::unique_ptr<IRObjectFile>>
112 IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
113   Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
114   if (!BCOrErr)
115     return BCOrErr.takeError();
116 
117   Expected<std::vector<BitcodeModule>> BMsOrErr =
118       getBitcodeModuleList(*BCOrErr);
119   if (!BMsOrErr)
120     return BMsOrErr.takeError();
121 
122   std::vector<std::unique_ptr<Module>> Mods;
123   for (auto BM : *BMsOrErr) {
124     Expected<std::unique_ptr<Module>> MOrErr =
125         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
126                          /*IsImporting*/ false);
127     if (!MOrErr)
128       return MOrErr.takeError();
129 
130     Mods.push_back(std::move(*MOrErr));
131   }
132 
133   return std::unique_ptr<IRObjectFile>(
134       new IRObjectFile(*BCOrErr, std::move(Mods)));
135 }
136 
137 Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
138   IRSymtabFile F;
139   Expected<MemoryBufferRef> BCOrErr =
140       IRObjectFile::findBitcodeInMemBuffer(MBRef);
141   if (!BCOrErr)
142     return BCOrErr.takeError();
143 
144   Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
145   if (!BFCOrErr)
146     return BFCOrErr.takeError();
147 
148   Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr);
149   if (!FCOrErr)
150     return FCOrErr.takeError();
151 
152   F.Mods = std::move(BFCOrErr->Mods);
153   F.Symtab = std::move(FCOrErr->Symtab);
154   F.Strtab = std::move(FCOrErr->Strtab);
155   F.TheReader = std::move(FCOrErr->TheReader);
156   return std::move(F);
157 }
158