1 //===----------- Mangling.cpp -- Name Mangling Utilities for ORC ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/Mangling.h" 10 #include "llvm/IR/Constants.h" 11 #include "llvm/IR/Mangler.h" 12 #include "llvm/Object/MachO.h" 13 #include "llvm/Object/ObjectFile.h" 14 #include "llvm/Support/Debug.h" 15 16 #define DEBUG_TYPE "orc" 17 18 namespace llvm { 19 namespace orc { 20 21 MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL) 22 : ES(ES), DL(DL) {} 23 24 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) { 25 std::string MangledName; 26 { 27 raw_string_ostream MangledNameStream(MangledName); 28 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 29 } 30 return ES.intern(MangledName); 31 } 32 33 void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO, 34 ArrayRef<GlobalValue *> GVs, 35 SymbolFlagsMap &SymbolFlags, 36 SymbolNameToDefinitionMap *SymbolToDefinition) { 37 if (GVs.empty()) 38 return; 39 40 MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout()); 41 for (auto *G : GVs) { 42 assert(G && "GVs cannot contain null elements"); 43 if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() || 44 G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage()) 45 continue; 46 47 if (G->isThreadLocal() && MO.EmulatedTLS) { 48 auto *GV = cast<GlobalVariable>(G); 49 50 auto Flags = JITSymbolFlags::fromGlobalValue(*GV); 51 52 auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str()); 53 SymbolFlags[EmuTLSV] = Flags; 54 if (SymbolToDefinition) 55 (*SymbolToDefinition)[EmuTLSV] = GV; 56 57 // If this GV has a non-zero initializer we'll need to emit an 58 // __emutls.t symbol too. 59 if (GV->hasInitializer()) { 60 const auto *InitVal = GV->getInitializer(); 61 62 // Skip zero-initializers. 63 if (isa<ConstantAggregateZero>(InitVal)) 64 continue; 65 const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal); 66 if (InitIntValue && InitIntValue->isZero()) 67 continue; 68 69 auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str()); 70 SymbolFlags[EmuTLST] = Flags; 71 if (SymbolToDefinition) 72 (*SymbolToDefinition)[EmuTLST] = GV; 73 } 74 continue; 75 } 76 77 // Otherwise we just need a normal linker mangling. 78 auto MangledName = Mangle(G->getName()); 79 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G); 80 if (SymbolToDefinition) 81 (*SymbolToDefinition)[MangledName] = G; 82 } 83 } 84 85 Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>> 86 getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 87 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 88 89 if (!Obj) 90 return Obj.takeError(); 91 92 bool IsMachO = isa<object::MachOObjectFile>(Obj->get()); 93 94 SymbolFlagsMap SymbolFlags; 95 for (auto &Sym : (*Obj)->symbols()) { 96 // Skip symbols not defined in this object file. 97 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) 98 continue; 99 100 // Skip symbols that are not global. 101 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) 102 continue; 103 104 // Skip symbols that have type SF_File. 105 if (auto SymType = Sym.getType()) { 106 if (*SymType == object::SymbolRef::ST_File) 107 continue; 108 } else 109 return SymType.takeError(); 110 111 auto Name = Sym.getName(); 112 if (!Name) 113 return Name.takeError(); 114 auto InternedName = ES.intern(*Name); 115 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 116 if (!SymFlags) 117 return SymFlags.takeError(); 118 119 // Strip the 'exported' flag from MachO linker-private symbols. 120 if (IsMachO && Name->startswith("l")) 121 *SymFlags &= ~JITSymbolFlags::Exported; 122 123 SymbolFlags[InternedName] = std::move(*SymFlags); 124 } 125 126 SymbolStringPtr InitSymbol; 127 128 if (IsMachO) { 129 auto &MachOObj = cast<object::MachOObjectFile>(*Obj->get()); 130 for (auto &Sec : MachOObj.sections()) { 131 auto SecType = MachOObj.getSectionType(Sec); 132 if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 133 size_t Counter = 0; 134 while (true) { 135 std::string InitSymString; 136 raw_string_ostream(InitSymString) 137 << "$." << ObjBuffer.getBufferIdentifier() << ".__inits." 138 << Counter++; 139 InitSymbol = ES.intern(InitSymString); 140 if (SymbolFlags.count(InitSymbol)) 141 continue; 142 SymbolFlags[InitSymbol] = 143 JITSymbolFlags::MaterializationSideEffectsOnly; 144 break; 145 } 146 break; 147 } 148 } 149 } 150 151 return std::make_pair(std::move(SymbolFlags), std::move(InitSymbol)); 152 } 153 154 } // End namespace orc. 155 } // End namespace llvm. 156