Commit 00925aad authored by Fangrui Song's avatar Fangrui Song
Browse files

[ELF][PPC32] Fix canonical PLTs when the order does not match the PLT order

Reviewed By: Bdragon28

Differential Revision: https://reviews.llvm.org/D75394
parent 718cbd39
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -76,8 +76,7 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
  // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
  uint32_t glink = in.plt->getVA(); // VA of .glink
  if (!config->isPic) {
    for (const Symbol *sym : in.plt->entries)
      if (sym->needsPltAddr) {
    for (const Symbol *sym : cast<PPC32GlinkSection>(in.plt)->canonical_plts) {
      writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
      buf += 16;
      glink += 16;
+1 −0
Original line number Diff line number Diff line
@@ -1226,6 +1226,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
          // PPC32 canonical PLT entries are at the beginning of .glink
          cast<Defined>(sym).value = in.plt->headerSize;
          in.plt->headerSize += 16;
          cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
        }
      }
      sym.needsPltAddr = true;
+15 −10
Original line number Diff line number Diff line
@@ -2447,12 +2447,9 @@ PltSection::PltSection()
    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
      headerSize(target->pltHeaderSize) {
  // On PowerPC, this section contains lazy symbol resolvers.
  if (config->emachine == EM_PPC || config->emachine == EM_PPC64) {
  if (config->emachine == EM_PPC64) {
    name = ".glink";
    alignment = 4;
    // PLTresolve is at the end.
    if (config->emachine == EM_PPC)
      footerSize = 64;
  }

  // On x86 when IBT is enabled, this section contains the second PLT (lazy
@@ -2468,11 +2465,6 @@ PltSection::PltSection()
}

void PltSection::writeTo(uint8_t *buf) {
  if (config->emachine == EM_PPC) {
    writePPC32GlinkSection(buf, entries.size());
    return;
  }

  // At beginning of PLT, we have code to call the dynamic
  // linker to resolve dynsyms at runtime. Write such code.
  target->writePltHeader(buf);
@@ -2490,7 +2482,7 @@ void PltSection::addEntry(Symbol &sym) {
}

size_t PltSection::getSize() const {
  return headerSize + entries.size() * target->pltEntrySize + footerSize;
  return headerSize + entries.size() * target->pltEntrySize;
}

bool PltSection::isNeeded() const {
@@ -2544,6 +2536,19 @@ void IpltSection::addSymbols() {
  }
}

PPC32GlinkSection::PPC32GlinkSection() {
  name = ".glink";
  alignment = 4;
}

void PPC32GlinkSection::writeTo(uint8_t *buf) {
  writePPC32GlinkSection(buf, entries.size());
}

size_t PPC32GlinkSection::getSize() const {
  return headerSize + entries.size() * target->pltEntrySize + footerSize;
}

// This is an x86-only extra PLT section and used only when a security
// enhancement feature called CET is enabled. In this comment, I'll explain what
// the feature is and why we have two PLT sections if CET is enabled.
+10 −1
Original line number Diff line number Diff line
@@ -684,7 +684,6 @@ public:
  size_t getNumEntries() const { return entries.size(); }

  size_t headerSize;
  size_t footerSize = 0;

  std::vector<const Symbol *> entries;
};
@@ -705,6 +704,16 @@ public:
  void addEntry(Symbol &sym);
};

class PPC32GlinkSection : public PltSection {
public:
  PPC32GlinkSection();
  void writeTo(uint8_t *buf) override;
  size_t getSize() const override;

  std::vector<const Symbol *> canonical_plts;
  static constexpr size_t footerSize = 64;
};

// This is x86-only.
class IBTPltSection : public SyntheticSection {
public:
+2 −1
Original line number Diff line number Diff line
@@ -525,7 +525,8 @@ template <class ELFT> void createSyntheticSections() {
    add(in.ibtPlt);
  }

  in.plt = make<PltSection>();
  in.plt = config->emachine == EM_PPC ? make<PPC32GlinkSection>()
                                      : make<PltSection>();
  add(in.plt);
  in.iplt = make<IpltSection>();
  add(in.iplt);
Loading