Пример #1
0
MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  StringRef SectionName = GO->getSection();

  // Infer section flags from the section name if we can.
  Kind = getELFKindForNamedSection(SectionName, Kind);

  StringRef Group = "";
  unsigned Flags = getELFSectionFlags(Kind);
  if (const Comdat *C = getELFComdat(GO)) {
    Group = C->getName();
    Flags |= ELF::SHF_GROUP;
  }

  // A section can have at most one associated section. Put each global with
  // MD_associated in a unique section.
  unsigned UniqueID = MCContext::GenericSectionID;
  const MCSymbolELF *AssociatedSymbol = getAssociatedSymbol(GO, TM);
  if (AssociatedSymbol) {
    UniqueID = NextUniqueID++;
    Flags |= ELF::SHF_LINK_ORDER;
  }

  MCSectionELF *Section = getContext().getELFSection(
      SectionName, getELFSectionType(SectionName, Kind), Flags,
      /*EntrySize=*/0, Group, UniqueID, AssociatedSymbol);
  // Make sure that we did not get some other section with incompatible sh_link.
  // This should not be possible due to UniqueID code above.
  assert(Section->getAssociatedSymbol() == AssociatedSymbol);
  return Section;
}
Пример #2
0
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  unsigned Flags = getELFSectionFlags(Kind);

  // If we have -ffunction-section or -fdata-section then we should emit the
  // global value to a uniqued section specifically for it.
  bool EmitUniqueSection = false;
  if (!(Flags & ELF::SHF_MERGE) && !Kind.isCommon()) {
    if (Kind.isText())
      EmitUniqueSection = TM.getFunctionSections();
    else
      EmitUniqueSection = TM.getDataSections();
  }
  EmitUniqueSection |= GO->hasComdat();

  const MCSymbolELF *AssociatedSymbol = getAssociatedSymbol(GO, TM);
  if (AssociatedSymbol) {
    EmitUniqueSection = true;
    Flags |= ELF::SHF_LINK_ORDER;
  }

  MCSectionELF *Section = selectELFSectionForGlobal(
      getContext(), GO, Kind, getMangler(), TM, EmitUniqueSection, Flags,
      &NextUniqueID, AssociatedSymbol);
  assert(Section->getAssociatedSymbol() == AssociatedSymbol);
  return Section;
}
Пример #3
0
MCSectionELF *
ELFObjectWriter::createRelocationSection(MCContext &Ctx,
                                         const MCSectionELF &Sec) {
  if (Relocations[&Sec].empty())
    return nullptr;

  const StringRef SectionName = Sec.getSectionName();
  std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel";
  RelaSectionName += SectionName;

  unsigned EntrySize;
  if (hasRelocationAddend())
    EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
  else
    EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);

  unsigned Flags = 0;
  if (Sec.getFlags() & ELF::SHF_GROUP)
    Flags = ELF::SHF_GROUP;

  MCSectionELF *RelaSection = Ctx.createELFRelSection(
      RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
      Flags, EntrySize, Sec.getGroup(), &Sec);
  RelaSection->setAlignment(is64Bit() ? 8 : 4);
  return RelaSection;
}
Пример #4
0
MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  StringRef SectionName = GO->getSection();

  // Check if '#pragma clang section' name is applicable.
  // Note that pragma directive overrides -ffunction-section, -fdata-section
  // and so section name is exactly as user specified and not uniqued.
  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO);
  if (GV && GV->hasImplicitSection()) {
    auto Attrs = GV->getAttributes();
    if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) {
      SectionName = Attrs.getAttribute("bss-section").getValueAsString();
    } else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) {
      SectionName = Attrs.getAttribute("rodata-section").getValueAsString();
    } else if (Attrs.hasAttribute("data-section") && Kind.isData()) {
      SectionName = Attrs.getAttribute("data-section").getValueAsString();
    }
  }
  const Function *F = dyn_cast<Function>(GO);
  if (F && F->hasFnAttribute("implicit-section-name")) {
    SectionName = F->getFnAttribute("implicit-section-name").getValueAsString();
  }

  // Infer section flags from the section name if we can.
  Kind = getELFKindForNamedSection(SectionName, Kind);

  StringRef Group = "";
  unsigned Flags = getELFSectionFlags(Kind);
  if (const Comdat *C = getELFComdat(GO)) {
    Group = C->getName();
    Flags |= ELF::SHF_GROUP;
  }

  // A section can have at most one associated section. Put each global with
  // MD_associated in a unique section.
  unsigned UniqueID = MCContext::GenericSectionID;
  const MCSymbolELF *AssociatedSymbol = getAssociatedSymbol(GO, TM);
  if (AssociatedSymbol) {
    UniqueID = NextUniqueID++;
    Flags |= ELF::SHF_LINK_ORDER;
  }

  MCSectionELF *Section = getContext().getELFSection(
      SectionName, getELFSectionType(SectionName, Kind), Flags,
      /*EntrySize=*/0, Group, UniqueID, AssociatedSymbol);
  // Make sure that we did not get some other section with incompatible sh_link.
  // This should not be possible due to UniqueID code above.
  assert(Section->getAssociatedSymbol() == AssociatedSymbol);
  return Section;
}
Пример #5
0
void MipsRegInfoRecord::EmitMipsOptionRecord() {
  MCAssembler &MCA = Streamer->getAssembler();
  MipsTargetStreamer *MTS =
      static_cast<MipsTargetStreamer *>(Streamer->getTargetStreamer());

  Streamer->PushSection();

  // We need to distinguish between N64 and the rest because at the moment
  // we don't emit .Mips.options for other ELFs other than N64.
  // Since .reginfo has the same information as .Mips.options (ODK_REGINFO),
  // we can use the same abstraction (MipsRegInfoRecord class) to handle both.
  if (MTS->getABI().IsN64()) {
    // The EntrySize value of 1 seems strange since the records are neither
    // 1-byte long nor fixed length but it matches the value GAS emits.
    MCSectionELF *Sec =
        Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS,
                              ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, 1, "");
    MCA.registerSection(*Sec);
    Sec->setAlignment(8);
    Streamer->SwitchSection(Sec);

    Streamer->EmitIntValue(ELF::ODK_REGINFO, 1);  // kind
    Streamer->EmitIntValue(40, 1); // size
    Streamer->EmitIntValue(0, 2);  // section
    Streamer->EmitIntValue(0, 4);  // info
    Streamer->EmitIntValue(ri_gprmask, 4);
    Streamer->EmitIntValue(0, 4); // pad
    Streamer->EmitIntValue(ri_cprmask[0], 4);
    Streamer->EmitIntValue(ri_cprmask[1], 4);
    Streamer->EmitIntValue(ri_cprmask[2], 4);
    Streamer->EmitIntValue(ri_cprmask[3], 4);
    Streamer->EmitIntValue(ri_gp_value, 8);
  } else {
    MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO,
                                              ELF::SHF_ALLOC, 24, "");
    MCA.registerSection(*Sec);
    Sec->setAlignment(MTS->getABI().IsN32() ? 8 : 4);
    Streamer->SwitchSection(Sec);

    Streamer->EmitIntValue(ri_gprmask, 4);
    Streamer->EmitIntValue(ri_cprmask[0], 4);
    Streamer->EmitIntValue(ri_cprmask[1], 4);
    Streamer->EmitIntValue(ri_cprmask[2], 4);
    Streamer->EmitIntValue(ri_cprmask[3], 4);
    assert((ri_gp_value & 0xffffffff) == ri_gp_value);
    Streamer->EmitIntValue(ri_gp_value, 4);
  }

  Streamer->PopSection();
}
Пример #6
0
/// HasCommonSymbols - True if this section holds common symbols, this is
/// indicated on the ELF object file by a symbol with SHN_COMMON section
/// header index.
static bool HasCommonSymbols(const MCSectionELF &S) {
  // FIXME: this is wrong, a common symbol can be in .data for example.
  if (StringRef(S.getSectionName()).startswith(".gnu.linkonce."))
    return true;

  return false;
}
Пример #7
0
void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
                                   uint32_t GroupSymbolIndex, uint64_t Offset,
                                   uint64_t Size, const MCSectionELF &Section) {
  uint64_t sh_link = 0;
  uint64_t sh_info = 0;

  switch(Section.getType()) {
  default:
    // Nothing to do.
    break;

  case ELF::SHT_DYNAMIC:
    llvm_unreachable("SHT_DYNAMIC in a relocatable object");

  case ELF::SHT_REL:
  case ELF::SHT_RELA: {
    sh_link = SymbolTableIndex;
    assert(sh_link && ".symtab not found");
    const MCSection *InfoSection = Section.getAssociatedSection();
    sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection));
    break;
  }

  case ELF::SHT_SYMTAB:
  case ELF::SHT_DYNSYM:
    sh_link = StringTableIndex;
    sh_info = LastLocalSymbolIndex;
    break;

  case ELF::SHT_SYMTAB_SHNDX:
    sh_link = SymbolTableIndex;
    break;

  case ELF::SHT_GROUP:
    sh_link = SymbolTableIndex;
    sh_info = GroupSymbolIndex;
    break;
  }

  if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
    const MCSymbol *Sym = Section.getAssociatedSymbol();
    const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection());
    sh_link = SectionIndexMap.lookup(Sec);
  }

  WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
                   Section.getType(), Section.getFlags(), 0, Offset, Size,
                   sh_link, sh_info, Section.getAlignment(),
                   Section.getEntrySize());
}
Пример #8
0
void ELFObjectWriter::computeSymbolTable(
    MCAssembler &Asm, const MCAsmLayout &Layout,
    const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap,
    SectionOffsetsTy &SectionOffsets) {
  MCContext &Ctx = Asm.getContext();
  SymbolTableWriter Writer(*this, is64Bit());

  // Symbol table
  unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
  MCSectionELF *SymtabSection =
      Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
  SymtabSection->setAlignment(is64Bit() ? 8 : 4);
  SymbolTableIndex = addToSectionTable(SymtabSection);

  align(SymtabSection->getAlignment());
  uint64_t SecStart = getStream().tell();

  // The first entry is the undefined symbol entry.
  Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);

  std::vector<ELFSymbolData> LocalSymbolData;
  std::vector<ELFSymbolData> ExternalSymbolData;

  // Add the data for the symbols.
  bool HasLargeSectionIndex = false;
  for (const MCSymbol &S : Asm.symbols()) {
    const auto &Symbol = cast<MCSymbolELF>(S);
    bool Used = Symbol.isUsedInReloc();
    bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
    bool isSignature = Symbol.isSignature();

    if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature,
                    Renames.count(&Symbol)))
      continue;

    if (Symbol.isTemporary() && Symbol.isUndefined()) {
      Ctx.reportError(SMLoc(), "Undefined temporary symbol");
      continue;
    }

    ELFSymbolData MSD;
    MSD.Symbol = cast<MCSymbolELF>(&Symbol);

    bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
    assert(Local || !Symbol.isTemporary());

    if (Symbol.isAbsolute()) {
      MSD.SectionIndex = ELF::SHN_ABS;
    } else if (Symbol.isCommon()) {
      assert(!Local);
      MSD.SectionIndex = ELF::SHN_COMMON;
    } else if (Symbol.isUndefined()) {
      if (isSignature && !Used) {
        MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
        if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
          HasLargeSectionIndex = true;
      } else {
        MSD.SectionIndex = ELF::SHN_UNDEF;
      }
    } else {
      const MCSectionELF &Section =
          static_cast<const MCSectionELF &>(Symbol.getSection());
      MSD.SectionIndex = SectionIndexMap.lookup(&Section);
      assert(MSD.SectionIndex && "Invalid section index!");
      if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
        HasLargeSectionIndex = true;
    }

    // The @@@ in symbol version is replaced with @ in undefined symbols and @@
    // in defined ones.
    //
    // FIXME: All name handling should be done before we get to the writer,
    // including dealing with GNU-style version suffixes.  Fixing this isn't
    // trivial.
    //
    // We thus have to be careful to not perform the symbol version replacement
    // blindly:
    //
    // The ELF format is used on Windows by the MCJIT engine.  Thus, on
    // Windows, the ELFObjectWriter can encounter symbols mangled using the MS
    // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC
    // C++ name mangling can legally have "@@@" as a sub-string. In that case,
    // the EFLObjectWriter should not interpret the "@@@" sub-string as
    // specifying GNU-style symbol versioning. The ELFObjectWriter therefore
    // checks for the MSVC C++ name mangling prefix which is either "?", "@?",
    // "__imp_?" or "__imp_@?".
    //
    // It would have been interesting to perform the MS mangling prefix check
    // only when the target triple is of the form *-pc-windows-elf. But, it
    // seems that this information is not easily accessible from the
    // ELFObjectWriter.
    StringRef Name = Symbol.getName();
    SmallString<32> Buf;
    if (!Name.startswith("?") && !Name.startswith("@?") &&
        !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) {
      // This symbol isn't following the MSVC C++ name mangling convention. We
      // can thus safely interpret the @@@ in symbol names as specifying symbol
      // versioning.
      size_t Pos = Name.find("@@@");
      if (Pos != StringRef::npos) {
        Buf += Name.substr(0, Pos);
        unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
        Buf += Name.substr(Pos + Skip);
        Name = VersionSymSaver.save(Buf.c_str());
      }
    }

    // Sections have their own string table
    if (Symbol.getType() != ELF::STT_SECTION) {
      MSD.Name = Name;
      StrTabBuilder.add(Name);
    }

    if (Local)
      LocalSymbolData.push_back(MSD);
    else
      ExternalSymbolData.push_back(MSD);
  }

  // This holds the .symtab_shndx section index.
  unsigned SymtabShndxSectionIndex = 0;

  if (HasLargeSectionIndex) {
    MCSectionELF *SymtabShndxSection =
        Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
    SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
    SymtabShndxSection->setAlignment(4);
  }

  ArrayRef<std::string> FileNames = Asm.getFileNames();
  for (const std::string &Name : FileNames)
    StrTabBuilder.add(Name);

  StrTabBuilder.finalize();

  // File symbols are emitted first and handled separately from normal symbols,
  // i.e. a non-STT_FILE symbol with the same name may appear.
  for (const std::string &Name : FileNames)
    Writer.writeSymbol(StrTabBuilder.getOffset(Name),
                       ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
                       ELF::SHN_ABS, true);

  // Symbols are required to be in lexicographic order.
  array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
  array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());

  // Set the symbol indices. Local symbols must come before all other
  // symbols with non-local bindings.
  unsigned Index = FileNames.size() + 1;

  for (ELFSymbolData &MSD : LocalSymbolData) {
    unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
                               ? 0
                               : StrTabBuilder.getOffset(MSD.Name);
    MSD.Symbol->setIndex(Index++);
    writeSymbol(Writer, StringIndex, MSD, Layout);
  }

  // Write the symbol table entries.
  LastLocalSymbolIndex = Index;

  for (ELFSymbolData &MSD : ExternalSymbolData) {
    unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
    MSD.Symbol->setIndex(Index++);
    writeSymbol(Writer, StringIndex, MSD, Layout);
    assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
  }

  uint64_t SecEnd = getStream().tell();
  SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);

  ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
  if (ShndxIndexes.empty()) {
    assert(SymtabShndxSectionIndex == 0);
    return;
  }
  assert(SymtabShndxSectionIndex != 0);

  SecStart = getStream().tell();
  const MCSectionELF *SymtabShndxSection =
      SectionTable[SymtabShndxSectionIndex - 1];
  for (uint32_t Index : ShndxIndexes)
    write(Index);
  SecEnd = getStream().tell();
  SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
}
Пример #9
0
void ELFObjectWriter::writeObject(MCAssembler &Asm,
                                  const MCAsmLayout &Layout) {
  MCContext &Ctx = Asm.getContext();
  MCSectionELF *StrtabSection =
      Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
  StringTableIndex = addToSectionTable(StrtabSection);

  RevGroupMapTy RevGroupMap;
  SectionIndexMapTy SectionIndexMap;

  std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers;

  // Write out the ELF header ...
  writeHeader(Asm);

  // ... then the sections ...
  SectionOffsetsTy SectionOffsets;
  std::vector<MCSectionELF *> Groups;
  std::vector<MCSectionELF *> Relocations;
  for (MCSection &Sec : Asm) {
    MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);

    align(Section.getAlignment());

    // Remember the offset into the file for this section.
    uint64_t SecStart = getStream().tell();

    const MCSymbolELF *SignatureSymbol = Section.getGroup();
    writeSectionData(Asm, Section, Layout);

    uint64_t SecEnd = getStream().tell();
    SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);

    MCSectionELF *RelSection = createRelocationSection(Ctx, Section);

    if (SignatureSymbol) {
      Asm.registerSymbol(*SignatureSymbol);
      unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
      if (!GroupIdx) {
        MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
        GroupIdx = addToSectionTable(Group);
        Group->setAlignment(4);
        Groups.push_back(Group);
      }
      std::vector<const MCSectionELF *> &Members =
          GroupMembers[SignatureSymbol];
      Members.push_back(&Section);
      if (RelSection)
        Members.push_back(RelSection);
    }

    SectionIndexMap[&Section] = addToSectionTable(&Section);
    if (RelSection) {
      SectionIndexMap[RelSection] = addToSectionTable(RelSection);
      Relocations.push_back(RelSection);
    }
  }

  for (MCSectionELF *Group : Groups) {
    align(Group->getAlignment());

    // Remember the offset into the file for this section.
    uint64_t SecStart = getStream().tell();

    const MCSymbol *SignatureSymbol = Group->getGroup();
    assert(SignatureSymbol);
    write(uint32_t(ELF::GRP_COMDAT));
    for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) {
      uint32_t SecIndex = SectionIndexMap.lookup(Member);
      write(SecIndex);
    }

    uint64_t SecEnd = getStream().tell();
    SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
  }

  // Compute symbol table information.
  computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets);

  for (MCSectionELF *RelSection : Relocations) {
    align(RelSection->getAlignment());

    // Remember the offset into the file for this section.
    uint64_t SecStart = getStream().tell();

    writeRelocations(Asm,
                     cast<MCSectionELF>(*RelSection->getAssociatedSection()));

    uint64_t SecEnd = getStream().tell();
    SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
  }

  {
    uint64_t SecStart = getStream().tell();
    const MCSectionELF *Sec = createStringTable(Ctx);
    uint64_t SecEnd = getStream().tell();
    SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
  }

  uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
  align(NaturalAlignment);

  const uint64_t SectionHeaderOffset = getStream().tell();

  // ... then the section header table ...
  writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);

  uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
                             ? (uint16_t)ELF::SHN_UNDEF
                             : SectionTable.size() + 1;
  if (sys::IsLittleEndianHost != IsLittleEndian)
    sys::swapByteOrder(NumSections);
  unsigned NumSectionsOffset;

  if (is64Bit()) {
    uint64_t Val = SectionHeaderOffset;
    if (sys::IsLittleEndianHost != IsLittleEndian)
      sys::swapByteOrder(Val);
    getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
                       offsetof(ELF::Elf64_Ehdr, e_shoff));
    NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
  } else {
    uint32_t Val = SectionHeaderOffset;
    if (sys::IsLittleEndianHost != IsLittleEndian)
      sys::swapByteOrder(Val);
    getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
                       offsetof(ELF::Elf32_Ehdr, e_shoff));
    NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
  }
  getStream().pwrite(reinterpret_cast<char *>(&NumSections),
                     sizeof(NumSections), NumSectionsOffset);
}