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