brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · b9cee98 Raw
339 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"10#include "llvm/ExecutionEngine/JITSymbol.h"11#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"12#include "llvm/Object/COFF.h"13#include "llvm/Object/ELFObjectFile.h"14#include "llvm/Object/MachO.h"15#include "llvm/Object/ObjectFile.h"16#include "llvm/Object/XCOFFObjectFile.h"17#include <optional>18 19#define DEBUG_TYPE "orc"20 21namespace llvm {22namespace orc {23 24void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,25                   StringRef ObjFileName) {26  assert(!I.InitSymbol && "I already has an init symbol");27  size_t Counter = 0;28 29  do {30    std::string InitSymString;31    raw_string_ostream(InitSymString)32        << "$." << ObjFileName << ".__inits." << Counter++;33    I.InitSymbol = ES.intern(InitSymString);34  } while (I.SymbolFlags.count(I.InitSymbol));35 36  I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;37}38 39static Expected<MaterializationUnit::Interface>40getMachOObjectFileSymbolInfo(ExecutionSession &ES,41                             const object::MachOObjectFile &Obj) {42  MaterializationUnit::Interface I;43 44  for (auto &Sym : Obj.symbols()) {45    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();46    if (!SymFlagsOrErr)47      // TODO: Test this error.48      return SymFlagsOrErr.takeError();49 50    // Skip symbols not defined in this object file.51    if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)52      continue;53 54    // Skip symbols that are not global.55    if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))56      continue;57 58    // Skip symbols that have type SF_File.59    if (auto SymType = Sym.getType()) {60      if (*SymType == object::SymbolRef::ST_File)61        continue;62    } else63      return SymType.takeError();64 65    auto Name = Sym.getName();66    if (!Name)67      return Name.takeError();68    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);69    if (!SymFlags)70      return SymFlags.takeError();71 72    // Strip the 'exported' flag from MachO linker-private symbols.73    if (Name->starts_with("l"))74      *SymFlags &= ~JITSymbolFlags::Exported;75 76    I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);77  }78 79  for (auto &Sec : Obj.sections()) {80    auto SecType = Obj.getSectionType(Sec);81    if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {82      addInitSymbol(I, ES, Obj.getFileName());83      break;84    }85    auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());86    auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));87    if (isMachOInitializerSection(SegName, SecName)) {88      addInitSymbol(I, ES, Obj.getFileName());89      break;90    }91  }92 93  return I;94}95 96static Expected<MaterializationUnit::Interface>97getELFObjectFileSymbolInfo(ExecutionSession &ES,98                           const object::ELFObjectFileBase &Obj) {99  MaterializationUnit::Interface I;100 101  for (auto &Sym : Obj.symbols()) {102    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();103    if (!SymFlagsOrErr)104      // TODO: Test this error.105      return SymFlagsOrErr.takeError();106 107    // Skip symbols not defined in this object file.108    if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)109      continue;110 111    // Skip symbols that are not global.112    if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))113      continue;114 115    // Skip symbols that have type SF_File.116    if (auto SymType = Sym.getType()) {117      if (*SymType == object::SymbolRef::ST_File)118        continue;119    } else120      return SymType.takeError();121 122    auto Name = Sym.getName();123    if (!Name)124      return Name.takeError();125 126    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);127    if (!SymFlags)128      return SymFlags.takeError();129 130    // ELF STB_GNU_UNIQUE should map to Weak for ORC.131    if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)132      *SymFlags |= JITSymbolFlags::Weak;133 134    I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);135  }136 137  SymbolStringPtr InitSymbol;138  for (auto &Sec : Obj.sections()) {139    if (auto SecName = Sec.getName()) {140      if (isELFInitializerSection(*SecName)) {141        addInitSymbol(I, ES, Obj.getFileName());142        break;143      }144    }145  }146 147  return I;148}149 150static Expected<MaterializationUnit::Interface>151getCOFFObjectFileSymbolInfo(ExecutionSession &ES,152                            const object::COFFObjectFile &Obj) {153  MaterializationUnit::Interface I;154  std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(155      Obj.getNumberOfSections() + 1);156  for (auto &Sym : Obj.symbols()) {157    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();158    if (!SymFlagsOrErr)159      // TODO: Test this error.160      return SymFlagsOrErr.takeError();161 162    // Handle comdat symbols163    auto COFFSym = Obj.getCOFFSymbol(Sym);164    bool IsWeak = false;165    if (auto *Def = COFFSym.getSectionDefinition()) {166      auto Sec = Obj.getSection(COFFSym.getSectionNumber());167      if (!Sec)168        return Sec.takeError();169      if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&170          Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {171        ComdatDefs[COFFSym.getSectionNumber()] = *Def;172        continue;173      }174    }175    if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&176        ComdatDefs[COFFSym.getSectionNumber()]) {177      auto Def = ComdatDefs[COFFSym.getSectionNumber()];178      if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {179        IsWeak = true;180      }181      ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;182    } else {183      // Skip symbols not defined in this object file.184      if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)185        continue;186    }187 188    // Skip symbols that are not global.189    if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))190      continue;191 192    // Skip symbols that have type SF_File.193    if (auto SymType = Sym.getType()) {194      if (*SymType == object::SymbolRef::ST_File)195        continue;196    } else197      return SymType.takeError();198 199    auto Name = Sym.getName();200    if (!Name)201      return Name.takeError();202 203    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);204    if (!SymFlags)205      return SymFlags.takeError();206    *SymFlags |= JITSymbolFlags::Exported;207 208    // Weak external is always a function209    if (COFFSym.isWeakExternal())210      *SymFlags |= JITSymbolFlags::Callable;211 212    if (IsWeak)213      *SymFlags |= JITSymbolFlags::Weak;214 215    I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);216  }217 218  SymbolStringPtr InitSymbol;219  for (auto &Sec : Obj.sections()) {220    if (auto SecName = Sec.getName()) {221      if (isCOFFInitializerSection(*SecName)) {222        addInitSymbol(I, ES, Obj.getFileName());223        break;224      }225    } else226      return SecName.takeError();227  }228 229  return I;230}231 232Expected<MaterializationUnit::Interface>233getXCOFFObjectFileSymbolInfo(ExecutionSession &ES,234                             const object::ObjectFile &Obj) {235 236  MaterializationUnit::Interface I;237 238  for (auto &Sym : Obj.symbols()) {239    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();240    if (!SymFlagsOrErr)241      return SymFlagsOrErr.takeError();242    uint32_t Flags = *SymFlagsOrErr;243 244    // Skip undefined, non global and ST_File245    if (Flags & object::SymbolRef::SF_Undefined)246      continue;247    if (!(Flags & object::SymbolRef::SF_Global))248      continue;249 250    auto SymbolType = Sym.getType();251    if (!SymbolType)252      return SymbolType.takeError();253 254    if (*SymbolType == object::SymbolRef::ST_File)255      continue;256 257    auto Name = Sym.getName();258    if (!Name)259      return Name.takeError();260    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);261    if (!SymFlags)262      return SymFlags.takeError();263 264    // TODO: Revisit symbol visibility265    // On AIX, symbols with C_EXT and C_WEAKEXT symbols have no specified266    // visibility are considered to have Default scope for LinkGraph. When the267    // object is not a DSO, symbol visibility is not specified. In the absence268    // of an Export List, its reasonable to minimic roughly the behaviour of269    // -bexpall or CreateExportList.270    *SymFlags |= JITSymbolFlags::Exported;271 272    I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);273  }274  // TODO: Find all initialization symbols for c++ static initializers275  return I;276}277 278Expected<MaterializationUnit::Interface>279getGenericObjectFileSymbolInfo(ExecutionSession &ES,280                               const object::ObjectFile &Obj) {281  MaterializationUnit::Interface I;282 283  for (auto &Sym : Obj.symbols()) {284    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();285    if (!SymFlagsOrErr)286      // TODO: Test this error.287      return SymFlagsOrErr.takeError();288 289    // Skip symbols not defined in this object file.290    if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)291      continue;292 293    // Skip symbols that are not global.294    if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))295      continue;296 297    // Skip symbols that have type SF_File.298    if (auto SymType = Sym.getType()) {299      if (*SymType == object::SymbolRef::ST_File)300        continue;301    } else302      return SymType.takeError();303 304    auto Name = Sym.getName();305    if (!Name)306      return Name.takeError();307 308    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);309    if (!SymFlags)310      return SymFlags.takeError();311 312    I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);313  }314 315  return I;316}317 318Expected<MaterializationUnit::Interface>319getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {320  auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);321 322  if (!Obj)323    return Obj.takeError();324 325  if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))326    return getMachOObjectFileSymbolInfo(ES, *MachOObj);327  else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))328    return getELFObjectFileSymbolInfo(ES, *ELFObj);329  else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))330    return getCOFFObjectFileSymbolInfo(ES, *COFFObj);331  else if (auto *XCOFFObj = dyn_cast<object::XCOFFObjectFile>(Obj->get()))332    return getXCOFFObjectFileSymbolInfo(ES, *XCOFFObj);333 334  return getGenericObjectFileSymbolInfo(ES, **Obj);335}336 337} // End namespace orc.338} // End namespace llvm.339