xref: /llvm-project/llvm/lib/Object/IRObjectFile.cpp (revision e32baa0c3e191396cbbdedf2b79fcdebd3e4fc50)
1 //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the IRObjectFile class implementation.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Object/IRObjectFile.h"
15 #include "RecordStreamer.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Bitcode/BitcodeReader.h"
18 #include "llvm/IR/GVMaterializer.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/Mangler.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/MC/MCAsmInfo.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCObjectFileInfo.h"
26 #include "llvm/MC/MCParser/MCAsmParser.h"
27 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
28 #include "llvm/MC/MCRegisterInfo.h"
29 #include "llvm/MC/MCSubtargetInfo.h"
30 #include "llvm/Object/ObjectFile.h"
31 #include "llvm/Support/MemoryBuffer.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Support/raw_ostream.h"
35 using namespace llvm;
36 using namespace object;
37 
38 IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod)
39     : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) {
40   Mang.reset(new Mangler());
41 
42   for (Function &F : *M)
43     SymTab.push_back(&F);
44   for (GlobalVariable &GV : M->globals())
45     SymTab.push_back(&GV);
46   for (GlobalAlias &GA : M->aliases())
47     SymTab.push_back(&GA);
48 
49   CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(),
50                           [this](StringRef Name, BasicSymbolRef::Flags Flags) {
51                             SymTab.push_back(new (AsmSymbols.Allocate())
52                                                  AsmSymbol(Name, Flags));
53                           });
54 }
55 
56 // Parse inline ASM and collect the list of symbols that are not defined in
57 // the current module. This is inspired from IRObjectFile.
58 void IRObjectFile::CollectAsmUndefinedRefs(
59     const Triple &TT, StringRef InlineAsm,
60     function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) {
61   if (InlineAsm.empty())
62     return;
63 
64   std::string Err;
65   const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
66   assert(T && T->hasMCAsmParser());
67 
68   std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
69   if (!MRI)
70     return;
71 
72   std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str()));
73   if (!MAI)
74     return;
75 
76   std::unique_ptr<MCSubtargetInfo> STI(
77       T->createMCSubtargetInfo(TT.str(), "", ""));
78   if (!STI)
79     return;
80 
81   std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
82   if (!MCII)
83     return;
84 
85   MCObjectFileInfo MOFI;
86   MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
87   MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx);
88   RecordStreamer Streamer(MCCtx);
89   T->createNullTargetStreamer(Streamer);
90 
91   std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
92   SourceMgr SrcMgr;
93   SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
94   std::unique_ptr<MCAsmParser> Parser(
95       createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
96 
97   MCTargetOptions MCOptions;
98   std::unique_ptr<MCTargetAsmParser> TAP(
99       T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
100   if (!TAP)
101     return;
102 
103   Parser->setTargetParser(*TAP);
104   if (Parser->Run(false))
105     return;
106 
107   for (auto &KV : Streamer) {
108     StringRef Key = KV.first();
109     RecordStreamer::State Value = KV.second;
110     uint32_t Res = BasicSymbolRef::SF_None;
111     switch (Value) {
112     case RecordStreamer::NeverSeen:
113       llvm_unreachable("NeverSeen should have been replaced earlier");
114     case RecordStreamer::DefinedGlobal:
115       Res |= BasicSymbolRef::SF_Global;
116       break;
117     case RecordStreamer::Defined:
118       break;
119     case RecordStreamer::Global:
120     case RecordStreamer::Used:
121       Res |= BasicSymbolRef::SF_Undefined;
122       Res |= BasicSymbolRef::SF_Global;
123       break;
124     case RecordStreamer::DefinedWeak:
125       Res |= BasicSymbolRef::SF_Weak;
126       Res |= BasicSymbolRef::SF_Global;
127       break;
128     case RecordStreamer::UndefinedWeak:
129       Res |= BasicSymbolRef::SF_Weak;
130       Res |= BasicSymbolRef::SF_Undefined;
131     }
132     AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res));
133   }
134 }
135 
136 IRObjectFile::~IRObjectFile() {}
137 
138 void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
139   Symb.p += sizeof(Sym);
140 }
141 
142 std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
143                                               DataRefImpl Symb) const {
144   Sym S = getSym(Symb);
145   if (S.is<AsmSymbol *>()) {
146     OS << S.get<AsmSymbol *>()->first;
147     return std::error_code();
148   }
149 
150   auto *GV = S.get<GlobalValue *>();
151   if (GV->hasDLLImportStorageClass())
152     OS << "__imp_";
153 
154   if (Mang)
155     Mang->getNameWithPrefix(OS, GV, false);
156   else
157     OS << GV->getName();
158 
159   return std::error_code();
160 }
161 
162 uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
163   Sym S = getSym(Symb);
164   if (S.is<AsmSymbol *>())
165     return S.get<AsmSymbol *>()->second;
166 
167   auto *GV = S.get<GlobalValue *>();
168 
169   uint32_t Res = BasicSymbolRef::SF_None;
170   if (GV->isDeclarationForLinker())
171     Res |= BasicSymbolRef::SF_Undefined;
172   else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
173     Res |= BasicSymbolRef::SF_Hidden;
174   if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
175     if (GVar->isConstant())
176       Res |= BasicSymbolRef::SF_Const;
177   }
178   if (GV->hasPrivateLinkage())
179     Res |= BasicSymbolRef::SF_FormatSpecific;
180   if (!GV->hasLocalLinkage())
181     Res |= BasicSymbolRef::SF_Global;
182   if (GV->hasCommonLinkage())
183     Res |= BasicSymbolRef::SF_Common;
184   if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
185       GV->hasExternalWeakLinkage())
186     Res |= BasicSymbolRef::SF_Weak;
187 
188   if (GV->getName().startswith("llvm."))
189     Res |= BasicSymbolRef::SF_FormatSpecific;
190   else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
191     if (Var->getSection() == "llvm.metadata")
192       Res |= BasicSymbolRef::SF_FormatSpecific;
193   }
194 
195   return Res;
196 }
197 
198 GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) {
199   return getSym(Symb).dyn_cast<GlobalValue *>();
200 }
201 
202 std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); }
203 
204 basic_symbol_iterator IRObjectFile::symbol_begin() const {
205   DataRefImpl Ret;
206   Ret.p = reinterpret_cast<uintptr_t>(SymTab.data());
207   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
208 }
209 
210 basic_symbol_iterator IRObjectFile::symbol_end() const {
211   DataRefImpl Ret;
212   Ret.p = reinterpret_cast<uintptr_t>(SymTab.data() + SymTab.size());
213   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
214 }
215 
216 ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
217   for (const SectionRef &Sec : Obj.sections()) {
218     if (Sec.isBitcode()) {
219       StringRef SecContents;
220       if (std::error_code EC = Sec.getContents(SecContents))
221         return EC;
222       return MemoryBufferRef(SecContents, Obj.getFileName());
223     }
224   }
225 
226   return object_error::bitcode_section_not_found;
227 }
228 
229 ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
230   sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
231   switch (Type) {
232   case sys::fs::file_magic::bitcode:
233     return Object;
234   case sys::fs::file_magic::elf_relocatable:
235   case sys::fs::file_magic::macho_object:
236   case sys::fs::file_magic::coff_object: {
237     Expected<std::unique_ptr<ObjectFile>> ObjFile =
238         ObjectFile::createObjectFile(Object, Type);
239     if (!ObjFile)
240       return errorToErrorCode(ObjFile.takeError());
241     return findBitcodeInObject(*ObjFile->get());
242   }
243   default:
244     return object_error::invalid_file_type;
245   }
246 }
247 
248 Expected<std::unique_ptr<IRObjectFile>>
249 llvm::object::IRObjectFile::create(MemoryBufferRef Object,
250                                    LLVMContext &Context) {
251   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
252   if (!BCOrErr)
253     return errorCodeToError(BCOrErr.getError());
254 
255   Expected<std::unique_ptr<Module>> MOrErr =
256       getLazyBitcodeModule(*BCOrErr, Context,
257                            /*ShouldLazyLoadMetadata*/ true);
258   if (!MOrErr)
259     return MOrErr.takeError();
260 
261   std::unique_ptr<Module> &M = MOrErr.get();
262   return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M));
263 }
264