1 //===- IRSymtab.cpp - implementation of IR symbol tables --------*- 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 #include "llvm/Object/IRSymtab.h" 11 #include "llvm/Analysis/ObjectUtils.h" 12 #include "llvm/IR/Mangler.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/MC/StringTableBuilder.h" 15 #include "llvm/Object/ModuleSymbolTable.h" 16 #include "llvm/Support/Allocator.h" 17 #include "llvm/Support/StringSaver.h" 18 19 using namespace llvm; 20 using namespace irsymtab; 21 22 namespace { 23 24 /// Stores the temporary state that is required to build an IR symbol table. 25 struct Builder { 26 SmallVector<char, 0> &Symtab; 27 SmallVector<char, 0> &Strtab; 28 Builder(SmallVector<char, 0> &Symtab, SmallVector<char, 0> &Strtab) 29 : Symtab(Symtab), Strtab(Strtab) {} 30 31 StringTableBuilder StrtabBuilder{StringTableBuilder::ELF}; 32 33 BumpPtrAllocator Alloc; 34 StringSaver Saver{Alloc}; 35 36 DenseMap<const Comdat *, unsigned> ComdatMap; 37 ModuleSymbolTable Msymtab; 38 SmallPtrSet<GlobalValue *, 8> Used; 39 Mangler Mang; 40 Triple TT; 41 42 std::vector<storage::Comdat> Comdats; 43 std::vector<storage::Module> Mods; 44 std::vector<storage::Symbol> Syms; 45 std::vector<storage::Uncommon> Uncommons; 46 47 std::string COFFLinkerOpts; 48 raw_string_ostream COFFLinkerOptsOS{COFFLinkerOpts}; 49 50 void setStr(storage::Str &S, StringRef Value) { 51 S.Offset = StrtabBuilder.add(Value); 52 } 53 template <typename T> 54 void writeRange(storage::Range<T> &R, const std::vector<T> &Objs) { 55 R.Offset = Symtab.size(); 56 R.Size = Objs.size(); 57 Symtab.insert(Symtab.end(), reinterpret_cast<const char *>(Objs.data()), 58 reinterpret_cast<const char *>(Objs.data() + Objs.size())); 59 } 60 61 Error addModule(Module *M); 62 Error addSymbol(ModuleSymbolTable::Symbol Sym); 63 64 Error build(ArrayRef<Module *> Mods); 65 }; 66 67 Error Builder::addModule(Module *M) { 68 collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); 69 70 storage::Module Mod; 71 Mod.Begin = Msymtab.symbols().size(); 72 Msymtab.addModule(M); 73 Mod.End = Msymtab.symbols().size(); 74 Mods.push_back(Mod); 75 76 if (TT.isOSBinFormatCOFF()) { 77 if (auto E = M->materializeMetadata()) 78 return E; 79 if (Metadata *Val = M->getModuleFlag("Linker Options")) { 80 MDNode *LinkerOptions = cast<MDNode>(Val); 81 for (const MDOperand &MDOptions : LinkerOptions->operands()) 82 for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands()) 83 COFFLinkerOptsOS << " " << cast<MDString>(MDOption)->getString(); 84 } 85 } 86 87 return Error::success(); 88 } 89 90 Error Builder::addSymbol(ModuleSymbolTable::Symbol Msym) { 91 Syms.emplace_back(); 92 storage::Symbol &Sym = Syms.back(); 93 Sym = {}; 94 95 Sym.UncommonIndex = -1; 96 storage::Uncommon *Unc = nullptr; 97 auto Uncommon = [&]() -> storage::Uncommon & { 98 if (Unc) 99 return *Unc; 100 Sym.UncommonIndex = Uncommons.size(); 101 Uncommons.emplace_back(); 102 Unc = &Uncommons.back(); 103 *Unc = {}; 104 setStr(Unc->COFFWeakExternFallbackName, ""); 105 return *Unc; 106 }; 107 108 SmallString<64> Name; 109 { 110 raw_svector_ostream OS(Name); 111 Msymtab.printSymbolName(OS, Msym); 112 } 113 setStr(Sym.Name, Saver.save(StringRef(Name))); 114 115 auto Flags = Msymtab.getSymbolFlags(Msym); 116 if (Flags & object::BasicSymbolRef::SF_Undefined) 117 Sym.Flags |= 1 << storage::Symbol::FB_undefined; 118 if (Flags & object::BasicSymbolRef::SF_Weak) 119 Sym.Flags |= 1 << storage::Symbol::FB_weak; 120 if (Flags & object::BasicSymbolRef::SF_Common) 121 Sym.Flags |= 1 << storage::Symbol::FB_common; 122 if (Flags & object::BasicSymbolRef::SF_Indirect) 123 Sym.Flags |= 1 << storage::Symbol::FB_indirect; 124 if (Flags & object::BasicSymbolRef::SF_Global) 125 Sym.Flags |= 1 << storage::Symbol::FB_global; 126 if (Flags & object::BasicSymbolRef::SF_FormatSpecific) 127 Sym.Flags |= 1 << storage::Symbol::FB_format_specific; 128 129 Sym.ComdatIndex = -1; 130 auto *GV = Msym.dyn_cast<GlobalValue *>(); 131 if (!GV) { 132 setStr(Sym.IRName, ""); 133 return Error::success(); 134 } 135 136 setStr(Sym.IRName, GV->getName()); 137 138 if (Used.count(GV)) 139 Sym.Flags |= 1 << storage::Symbol::FB_used; 140 if (GV->isThreadLocal()) 141 Sym.Flags |= 1 << storage::Symbol::FB_tls; 142 if (GV->hasGlobalUnnamedAddr()) 143 Sym.Flags |= 1 << storage::Symbol::FB_unnamed_addr; 144 if (canBeOmittedFromSymbolTable(GV)) 145 Sym.Flags |= 1 << storage::Symbol::FB_may_omit; 146 Sym.Flags |= unsigned(GV->getVisibility()) << storage::Symbol::FB_visibility; 147 148 if (Flags & object::BasicSymbolRef::SF_Common) { 149 Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize( 150 GV->getType()->getElementType()); 151 Uncommon().CommonAlign = GV->getAlignment(); 152 } 153 154 const GlobalObject *Base = GV->getBaseObject(); 155 if (!Base) 156 return make_error<StringError>("Unable to determine comdat of alias!", 157 inconvertibleErrorCode()); 158 if (const Comdat *C = Base->getComdat()) { 159 auto P = ComdatMap.insert(std::make_pair(C, Comdats.size())); 160 Sym.ComdatIndex = P.first->second; 161 162 if (P.second) { 163 storage::Comdat Comdat; 164 setStr(Comdat.Name, C->getName()); 165 Comdats.push_back(Comdat); 166 } 167 } 168 169 if (TT.isOSBinFormatCOFF()) { 170 emitLinkerFlagsForGlobalCOFF(COFFLinkerOptsOS, GV, TT, Mang); 171 172 if ((Flags & object::BasicSymbolRef::SF_Weak) && 173 (Flags & object::BasicSymbolRef::SF_Indirect)) { 174 std::string FallbackName; 175 raw_string_ostream OS(FallbackName); 176 Msymtab.printSymbolName( 177 OS, cast<GlobalValue>( 178 cast<GlobalAlias>(GV)->getAliasee()->stripPointerCasts())); 179 OS.flush(); 180 setStr(Uncommon().COFFWeakExternFallbackName, Saver.save(FallbackName)); 181 } 182 } 183 184 return Error::success(); 185 } 186 187 Error Builder::build(ArrayRef<Module *> IRMods) { 188 storage::Header Hdr; 189 190 assert(!IRMods.empty()); 191 setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName()); 192 TT = Triple(IRMods[0]->getTargetTriple()); 193 194 // This adds the symbols for each module to Msymtab. 195 for (auto *M : IRMods) 196 if (Error Err = addModule(M)) 197 return Err; 198 199 for (ModuleSymbolTable::Symbol Msym : Msymtab.symbols()) 200 if (Error Err = addSymbol(Msym)) 201 return Err; 202 203 COFFLinkerOptsOS.flush(); 204 setStr(Hdr.COFFLinkerOpts, COFFLinkerOpts); 205 206 // We are about to fill in the header's range fields, so reserve space for it 207 // and copy it in afterwards. 208 Symtab.resize(sizeof(storage::Header)); 209 writeRange(Hdr.Modules, Mods); 210 writeRange(Hdr.Comdats, Comdats); 211 writeRange(Hdr.Symbols, Syms); 212 writeRange(Hdr.Uncommons, Uncommons); 213 214 *reinterpret_cast<storage::Header *>(Symtab.data()) = Hdr; 215 216 raw_svector_ostream OS(Strtab); 217 StrtabBuilder.finalizeInOrder(); 218 StrtabBuilder.write(OS); 219 220 return Error::success(); 221 } 222 223 } // anonymous namespace 224 225 Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab, 226 SmallVector<char, 0> &Strtab) { 227 return Builder(Symtab, Strtab).build(Mods); 228 } 229