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