1 //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===// 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/ObjectFileInterface.h" 10 #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" 11 #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" 12 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 13 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14 #include "llvm/Object/COFF.h" 15 #include "llvm/Object/ELFObjectFile.h" 16 #include "llvm/Object/MachO.h" 17 #include "llvm/Object/ObjectFile.h" 18 #include "llvm/Support/Debug.h" 19 #include <optional> 20 21 #define DEBUG_TYPE "orc" 22 23 namespace llvm { 24 namespace orc { 25 26 void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, 27 StringRef ObjFileName) { 28 assert(!I.InitSymbol && "I already has an init symbol"); 29 size_t Counter = 0; 30 31 do { 32 std::string InitSymString; 33 raw_string_ostream(InitSymString) 34 << "$." << ObjFileName << ".__inits." << Counter++; 35 I.InitSymbol = ES.intern(InitSymString); 36 } while (I.SymbolFlags.count(I.InitSymbol)); 37 38 I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; 39 } 40 41 static Expected<MaterializationUnit::Interface> 42 getMachOObjectFileSymbolInfo(ExecutionSession &ES, 43 const object::MachOObjectFile &Obj) { 44 MaterializationUnit::Interface I; 45 46 for (auto &Sym : Obj.symbols()) { 47 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 48 if (!SymFlagsOrErr) 49 // TODO: Test this error. 50 return SymFlagsOrErr.takeError(); 51 52 // Skip symbols not defined in this object file. 53 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 54 continue; 55 56 // Skip symbols that are not global. 57 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 58 continue; 59 60 // Skip symbols that have type SF_File. 61 if (auto SymType = Sym.getType()) { 62 if (*SymType == object::SymbolRef::ST_File) 63 continue; 64 } else 65 return SymType.takeError(); 66 67 auto Name = Sym.getName(); 68 if (!Name) 69 return Name.takeError(); 70 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 71 if (!SymFlags) 72 return SymFlags.takeError(); 73 74 // Strip the 'exported' flag from MachO linker-private symbols. 75 if (Name->starts_with("l")) 76 *SymFlags &= ~JITSymbolFlags::Exported; 77 78 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 79 } 80 81 for (auto &Sec : Obj.sections()) { 82 auto SecType = Obj.getSectionType(Sec); 83 if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 84 addInitSymbol(I, ES, Obj.getFileName()); 85 break; 86 } 87 auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); 88 auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); 89 if (isMachOInitializerSection(SegName, SecName)) { 90 addInitSymbol(I, ES, Obj.getFileName()); 91 break; 92 } 93 } 94 95 return I; 96 } 97 98 static Expected<MaterializationUnit::Interface> 99 getELFObjectFileSymbolInfo(ExecutionSession &ES, 100 const object::ELFObjectFileBase &Obj) { 101 MaterializationUnit::Interface I; 102 103 for (auto &Sym : Obj.symbols()) { 104 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 105 if (!SymFlagsOrErr) 106 // TODO: Test this error. 107 return SymFlagsOrErr.takeError(); 108 109 // Skip symbols not defined in this object file. 110 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 111 continue; 112 113 // Skip symbols that are not global. 114 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 115 continue; 116 117 // Skip symbols that have type SF_File. 118 if (auto SymType = Sym.getType()) { 119 if (*SymType == object::SymbolRef::ST_File) 120 continue; 121 } else 122 return SymType.takeError(); 123 124 auto Name = Sym.getName(); 125 if (!Name) 126 return Name.takeError(); 127 128 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 129 if (!SymFlags) 130 return SymFlags.takeError(); 131 132 // ELF STB_GNU_UNIQUE should map to Weak for ORC. 133 if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) 134 *SymFlags |= JITSymbolFlags::Weak; 135 136 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 137 } 138 139 SymbolStringPtr InitSymbol; 140 for (auto &Sec : Obj.sections()) { 141 if (auto SecName = Sec.getName()) { 142 if (isELFInitializerSection(*SecName)) { 143 addInitSymbol(I, ES, Obj.getFileName()); 144 break; 145 } 146 } 147 } 148 149 return I; 150 } 151 152 static Expected<MaterializationUnit::Interface> 153 getCOFFObjectFileSymbolInfo(ExecutionSession &ES, 154 const object::COFFObjectFile &Obj) { 155 MaterializationUnit::Interface I; 156 std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs( 157 Obj.getNumberOfSections() + 1); 158 for (auto &Sym : Obj.symbols()) { 159 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 160 if (!SymFlagsOrErr) 161 // TODO: Test this error. 162 return SymFlagsOrErr.takeError(); 163 164 // Handle comdat symbols 165 auto COFFSym = Obj.getCOFFSymbol(Sym); 166 bool IsWeak = false; 167 if (auto *Def = COFFSym.getSectionDefinition()) { 168 auto Sec = Obj.getSection(COFFSym.getSectionNumber()); 169 if (!Sec) 170 return Sec.takeError(); 171 if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) && 172 Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { 173 ComdatDefs[COFFSym.getSectionNumber()] = *Def; 174 continue; 175 } 176 } 177 if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) && 178 ComdatDefs[COFFSym.getSectionNumber()]) { 179 auto Def = ComdatDefs[COFFSym.getSectionNumber()]; 180 if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) { 181 IsWeak = true; 182 } 183 ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt; 184 } else { 185 // Skip symbols not defined in this object file. 186 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 187 continue; 188 } 189 190 // Skip symbols that are not global. 191 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 192 continue; 193 194 // Skip symbols that have type SF_File. 195 if (auto SymType = Sym.getType()) { 196 if (*SymType == object::SymbolRef::ST_File) 197 continue; 198 } else 199 return SymType.takeError(); 200 201 auto Name = Sym.getName(); 202 if (!Name) 203 return Name.takeError(); 204 205 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 206 if (!SymFlags) 207 return SymFlags.takeError(); 208 *SymFlags |= JITSymbolFlags::Exported; 209 210 // Weak external is always a function 211 if (COFFSym.isWeakExternal()) 212 *SymFlags |= JITSymbolFlags::Callable; 213 214 if (IsWeak) 215 *SymFlags |= JITSymbolFlags::Weak; 216 217 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 218 } 219 220 SymbolStringPtr InitSymbol; 221 for (auto &Sec : Obj.sections()) { 222 if (auto SecName = Sec.getName()) { 223 if (isCOFFInitializerSection(*SecName)) { 224 addInitSymbol(I, ES, Obj.getFileName()); 225 break; 226 } 227 } else 228 return SecName.takeError(); 229 } 230 231 return I; 232 } 233 234 Expected<MaterializationUnit::Interface> 235 getGenericObjectFileSymbolInfo(ExecutionSession &ES, 236 const object::ObjectFile &Obj) { 237 MaterializationUnit::Interface I; 238 239 for (auto &Sym : Obj.symbols()) { 240 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 241 if (!SymFlagsOrErr) 242 // TODO: Test this error. 243 return SymFlagsOrErr.takeError(); 244 245 // Skip symbols not defined in this object file. 246 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 247 continue; 248 249 // Skip symbols that are not global. 250 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 251 continue; 252 253 // Skip symbols that have type SF_File. 254 if (auto SymType = Sym.getType()) { 255 if (*SymType == object::SymbolRef::ST_File) 256 continue; 257 } else 258 return SymType.takeError(); 259 260 auto Name = Sym.getName(); 261 if (!Name) 262 return Name.takeError(); 263 264 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 265 if (!SymFlags) 266 return SymFlags.takeError(); 267 268 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 269 } 270 271 return I; 272 } 273 274 Expected<MaterializationUnit::Interface> 275 getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 276 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 277 278 if (!Obj) 279 return Obj.takeError(); 280 281 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) 282 return getMachOObjectFileSymbolInfo(ES, *MachOObj); 283 else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get())) 284 return getELFObjectFileSymbolInfo(ES, *ELFObj); 285 else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get())) 286 return getCOFFObjectFileSymbolInfo(ES, *COFFObj); 287 288 return getGenericObjectFileSymbolInfo(ES, **Obj); 289 } 290 291 } // End namespace orc. 292 } // End namespace llvm. 293