1 //===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===// 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 "RecordStreamer.h" 11 #include "llvm/IR/Mangler.h" 12 #include "llvm/IR/Module.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCSymbol.h" 15 16 using namespace llvm; 17 18 void RecordStreamer::markDefined(const MCSymbol &Symbol) { 19 State &S = Symbols[Symbol.getName()]; 20 switch (S) { 21 case DefinedGlobal: 22 case Global: 23 S = DefinedGlobal; 24 break; 25 case NeverSeen: 26 case Defined: 27 case Used: 28 S = Defined; 29 break; 30 case DefinedWeak: 31 break; 32 case UndefinedWeak: 33 S = DefinedWeak; 34 } 35 } 36 37 void RecordStreamer::markGlobal(const MCSymbol &Symbol, 38 MCSymbolAttr Attribute) { 39 State &S = Symbols[Symbol.getName()]; 40 switch (S) { 41 case DefinedGlobal: 42 case Defined: 43 S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal; 44 break; 45 46 case NeverSeen: 47 case Global: 48 case Used: 49 S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global; 50 break; 51 case UndefinedWeak: 52 case DefinedWeak: 53 break; 54 } 55 } 56 57 void RecordStreamer::markUsed(const MCSymbol &Symbol) { 58 State &S = Symbols[Symbol.getName()]; 59 switch (S) { 60 case DefinedGlobal: 61 case Defined: 62 case Global: 63 case DefinedWeak: 64 case UndefinedWeak: 65 break; 66 67 case NeverSeen: 68 case Used: 69 S = Used; 70 break; 71 } 72 } 73 74 void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } 75 76 RecordStreamer::RecordStreamer(MCContext &Context, const Module &M) 77 : MCStreamer(Context), M(M) {} 78 79 RecordStreamer::const_iterator RecordStreamer::begin() { 80 return Symbols.begin(); 81 } 82 83 RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } 84 85 void RecordStreamer::EmitInstruction(const MCInst &Inst, 86 const MCSubtargetInfo &STI, bool) { 87 MCStreamer::EmitInstruction(Inst, STI); 88 } 89 90 void RecordStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { 91 MCStreamer::EmitLabel(Symbol); 92 markDefined(*Symbol); 93 } 94 95 void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 96 markDefined(*Symbol); 97 MCStreamer::EmitAssignment(Symbol, Value); 98 } 99 100 bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 101 MCSymbolAttr Attribute) { 102 if (Attribute == MCSA_Global || Attribute == MCSA_Weak) 103 markGlobal(*Symbol, Attribute); 104 if (Attribute == MCSA_LazyReference) 105 markUsed(*Symbol); 106 return true; 107 } 108 109 void RecordStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 110 uint64_t Size, unsigned ByteAlignment) { 111 markDefined(*Symbol); 112 } 113 114 void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 115 unsigned ByteAlignment) { 116 markDefined(*Symbol); 117 } 118 119 RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) { 120 auto SI = Symbols.find(Sym->getName()); 121 if (SI == Symbols.end()) 122 return NeverSeen; 123 return SI->second; 124 } 125 126 void RecordStreamer::emitELFSymverDirective(StringRef AliasName, 127 const MCSymbol *Aliasee) { 128 SymverAliasMap[Aliasee].push_back(AliasName); 129 } 130 131 void RecordStreamer::flushSymverDirectives() { 132 // Mapping from mangled name to GV. 133 StringMap<const GlobalValue *> MangledNameMap; 134 // The name in the assembler will be mangled, but the name in the IR 135 // might not, so we first compute a mapping from mangled name to GV. 136 Mangler Mang; 137 SmallString<64> MangledName; 138 for (const GlobalValue &GV : M.global_values()) { 139 if (!GV.hasName()) 140 continue; 141 MangledName.clear(); 142 MangledName.reserve(GV.getName().size() + 1); 143 Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); 144 MangledNameMap[MangledName] = &GV; 145 } 146 147 // Walk all the recorded .symver aliases, and set up the binding 148 // for each alias. 149 for (auto &Symver : SymverAliasMap) { 150 const MCSymbol *Aliasee = Symver.first; 151 MCSymbolAttr Attr = MCSA_Invalid; 152 bool IsDefined = false; 153 154 // First check if the aliasee binding was recorded in the asm. 155 RecordStreamer::State state = getSymbolState(Aliasee); 156 switch (state) { 157 case RecordStreamer::Global: 158 case RecordStreamer::DefinedGlobal: 159 Attr = MCSA_Global; 160 break; 161 case RecordStreamer::UndefinedWeak: 162 case RecordStreamer::DefinedWeak: 163 Attr = MCSA_Weak; 164 break; 165 default: 166 break; 167 } 168 169 switch (state) { 170 case RecordStreamer::Defined: 171 case RecordStreamer::DefinedGlobal: 172 case RecordStreamer::DefinedWeak: 173 IsDefined = true; 174 break; 175 case RecordStreamer::NeverSeen: 176 case RecordStreamer::Global: 177 case RecordStreamer::Used: 178 case RecordStreamer::UndefinedWeak: 179 break; 180 } 181 182 if (Attr == MCSA_Invalid || !IsDefined) { 183 const GlobalValue *GV = M.getNamedValue(Aliasee->getName()); 184 if (!GV) { 185 auto MI = MangledNameMap.find(Aliasee->getName()); 186 if (MI != MangledNameMap.end()) 187 GV = MI->second; 188 } 189 if (GV) { 190 // If we don't have a symbol attribute from assembly, then check if 191 // the aliasee was defined in the IR. 192 if (Attr == MCSA_Invalid) { 193 if (GV->hasExternalLinkage()) 194 Attr = MCSA_Global; 195 else if (GV->hasLocalLinkage()) 196 Attr = MCSA_Local; 197 else if (GV->isWeakForLinker()) 198 Attr = MCSA_Weak; 199 } 200 IsDefined = IsDefined || !GV->isDeclarationForLinker(); 201 } 202 } 203 204 // Set the detected binding on each alias with this aliasee. 205 for (auto AliasName : Symver.second) { 206 std::pair<StringRef, StringRef> Split = AliasName.split("@@@"); 207 SmallString<128> NewName; 208 if (!Split.second.empty() && !Split.second.startswith("@")) { 209 // Special processing for "@@@" according 210 // https://sourceware.org/binutils/docs/as/Symver.html 211 const char *Separator = IsDefined ? "@@" : "@"; 212 AliasName = 213 (Split.first + Separator + Split.second).toStringRef(NewName); 214 } 215 MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 216 // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be 217 // converted into @ or @@. 218 const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext()); 219 if (IsDefined) 220 markDefined(*Alias); 221 // Don't use EmitAssignment override as it always marks alias as defined. 222 MCStreamer::EmitAssignment(Alias, Value); 223 if (Attr != MCSA_Invalid) 224 EmitSymbolAttribute(Alias, Attr); 225 } 226 } 227 } 228