| //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the IRObjectFile class implementation. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Object/IRObjectFile.h" | |
| #include "llvm/ADT/ArrayRef.h" | |
| #include "llvm/BinaryFormat/Magic.h" | |
| #include "llvm/Bitcode/BitcodeReader.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/Object/ObjectFile.h" | |
| using namespace llvm; | |
| using namespace object; | |
| namespace llvm { | |
| class LLVMContext; | |
| class raw_ostream; | |
| } // namespace llvm | |
| IRObjectFile::IRObjectFile(MemoryBufferRef Object, | |
| std::vector<std::unique_ptr<Module>> Mods) | |
| : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) { | |
| for (auto &M : this->Mods) | |
| SymTab.addModule(M.get()); | |
| } | |
| IRObjectFile::~IRObjectFile() = default; | |
| static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) { | |
| return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p); | |
| } | |
| void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { | |
| Symb.p += sizeof(ModuleSymbolTable::Symbol); | |
| } | |
| Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { | |
| SymTab.printSymbolName(OS, getSym(Symb)); | |
| return Error::success(); | |
| } | |
| Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { | |
| return SymTab.getSymbolFlags(getSym(Symb)); | |
| } | |
| basic_symbol_iterator IRObjectFile::symbol_begin() const { | |
| DataRefImpl Ret; | |
| Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data()); | |
| return basic_symbol_iterator(BasicSymbolRef(Ret, this)); | |
| } | |
| basic_symbol_iterator IRObjectFile::symbol_end() const { | |
| DataRefImpl Ret; | |
| Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() + | |
| SymTab.symbols().size()); | |
| return basic_symbol_iterator(BasicSymbolRef(Ret, this)); | |
| } | |
| StringRef IRObjectFile::getTargetTriple() const { | |
| // Each module must have the same target triple, so we arbitrarily access the | |
| // first one. | |
| return Mods[0]->getTargetTriple().str(); | |
| } | |
| Expected<MemoryBufferRef> | |
| IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { | |
| for (const SectionRef &Sec : Obj.sections()) { | |
| if (Sec.isBitcode()) { | |
| Expected<StringRef> Contents = Sec.getContents(); | |
| if (!Contents) | |
| return Contents.takeError(); | |
| if (Contents->size() <= 1) | |
| return errorCodeToError(object_error::bitcode_section_not_found); | |
| return MemoryBufferRef(*Contents, Obj.getFileName()); | |
| } | |
| } | |
| return errorCodeToError(object_error::bitcode_section_not_found); | |
| } | |
| Expected<MemoryBufferRef> | |
| IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { | |
| file_magic Type = identify_magic(Object.getBuffer()); | |
| switch (Type) { | |
| case file_magic::bitcode: | |
| return Object; | |
| case file_magic::elf_relocatable: | |
| case file_magic::macho_object: | |
| case file_magic::wasm_object: | |
| case file_magic::coff_object: { | |
| Expected<std::unique_ptr<ObjectFile>> ObjFile = | |
| ObjectFile::createObjectFile(Object, Type); | |
| if (!ObjFile) | |
| return ObjFile.takeError(); | |
| return findBitcodeInObject(*ObjFile->get()); | |
| } | |
| default: | |
| return errorCodeToError(object_error::invalid_file_type); | |
| } | |
| } | |
| Expected<std::unique_ptr<IRObjectFile>> | |
| IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) { | |
| Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); | |
| if (!BCOrErr) | |
| return BCOrErr.takeError(); | |
| Expected<std::vector<BitcodeModule>> BMsOrErr = | |
| getBitcodeModuleList(*BCOrErr); | |
| if (!BMsOrErr) | |
| return BMsOrErr.takeError(); | |
| std::vector<std::unique_ptr<Module>> Mods; | |
| for (auto BM : *BMsOrErr) { | |
| Expected<std::unique_ptr<Module>> MOrErr = | |
| BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true, | |
| /*IsImporting*/ false); | |
| if (!MOrErr) | |
| return MOrErr.takeError(); | |
| Mods.push_back(std::move(*MOrErr)); | |
| } | |
| return std::unique_ptr<IRObjectFile>( | |
| new IRObjectFile(*BCOrErr, std::move(Mods))); | |
| } | |
| Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) { | |
| IRSymtabFile F; | |
| Expected<MemoryBufferRef> BCOrErr = | |
| IRObjectFile::findBitcodeInMemBuffer(MBRef); | |
| if (!BCOrErr) | |
| return BCOrErr.takeError(); | |
| Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr); | |
| if (!BFCOrErr) | |
| return BFCOrErr.takeError(); | |
| Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr); | |
| if (!FCOrErr) | |
| return FCOrErr.takeError(); | |
| F.Mods = std::move(BFCOrErr->Mods); | |
| F.Symtab = std::move(FCOrErr->Symtab); | |
| F.Strtab = std::move(FCOrErr->Strtab); | |
| F.TheReader = std::move(FCOrErr->TheReader); | |
| return std::move(F); | |
| } |