Commit 572d1839 authored by Fangrui Song's avatar Fangrui Song
Browse files

[ELF] Add TargetInfo::adjustGotPcExpr for `R_GOT_PC` relaxations. NFC

With this change, `TargetInfo::adjustRelaxExpr` is only related to TLS
relaxations and a subsequent clean-up can delete the `data` parameter.

Differential Revision: https://reviews.llvm.org/D92079
parent ba74fa24
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -384,6 +384,8 @@ public:
  bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
  RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
                          RelExpr expr) const override;
  RelExpr adjustGotPcExpr(RelType type, int64_t addend,
                          const uint8_t *loc) const override;
  void relaxGot(uint8_t *loc, const Relocation &rel,
                uint64_t val) const override;
  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
@@ -1392,20 +1394,23 @@ bool PPC64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {

RelExpr PPC64::adjustRelaxExpr(RelType type, const uint8_t *data,
                               RelExpr expr) const {
  if (type != R_PPC64_GOT_TLSGD_PCREL34 && expr == R_RELAX_TLS_GD_TO_IE)
    return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
  if (expr == R_RELAX_TLS_LD_TO_LE)
    return R_RELAX_TLS_LD_TO_LE_ABS;
  return expr;
}

RelExpr PPC64::adjustGotPcExpr(RelType type, int64_t addend,
                               const uint8_t *loc) const {
  if ((type == R_PPC64_GOT_PCREL34 || type == R_PPC64_PCREL_OPT) &&
      config->pcRelOptimize) {
    // It only makes sense to optimize pld since paddi means that the address
    // of the object in the GOT is required rather than the object itself.
    assert(data && "Expecting an instruction encoding here");
    if ((readPrefixedInstruction(data) & 0xfc000000) == 0xe4000000)
    if ((readPrefixedInstruction(loc) & 0xfc000000) == 0xe4000000)
      return R_PPC64_RELAX_GOT_PC;
  }

  if (type != R_PPC64_GOT_TLSGD_PCREL34 && expr == R_RELAX_TLS_GD_TO_IE)
    return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
  if (expr == R_RELAX_TLS_LD_TO_LE)
    return R_RELAX_TLS_LD_TO_LE_ABS;
  return expr;
  return R_GOT_PC;
}

// Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement.
+9 −9
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ public:
  void applyJumpInstrMod(uint8_t *loc, JumpModType type,
                         unsigned size) const override;

  RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
                          RelExpr expr) const override;
  RelExpr adjustGotPcExpr(RelType type, int64_t addend,
                          const uint8_t *loc) const override;
  void relaxGot(uint8_t *loc, const Relocation &rel,
                uint64_t val) const override;
  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
@@ -728,12 +728,12 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
  }
}

RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data,
                                RelExpr relExpr) const {
RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
                                const uint8_t *loc) const {
  if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX)
    return relExpr;
  const uint8_t op = data[-2];
  const uint8_t modRm = data[-1];
    return R_GOT_PC;
  const uint8_t op = loc[-2];
  const uint8_t modRm = loc[-1];

  // FIXME: When PIC is disabled and foo is defined locally in the
  // lower 32 bit address space, memory operand in mov can be converted into
@@ -748,11 +748,11 @@ RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data,

  // We don't support test/binop instructions without a REX prefix.
  if (type == R_X86_64_GOTPCRELX)
    return relExpr;
    return R_GOT_PC;

  // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
  // If PIC then no relaxation is available.
  return config->isPic ? relExpr : R_RELAX_GOT_PC_NOPIC;
  return config->isPic ? R_GOT_PC : R_RELAX_GOT_PC_NOPIC;
}

// A subset of relaxations can only be applied for no-PIC. This method
+3 −3
Original line number Diff line number Diff line
@@ -1361,9 +1361,7 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
  // runtime, because the main executable is always at the beginning of a search
  // list. We can leverage that fact.
  if (!sym.isPreemptible && (!sym.isGnuIFunc() || config->zIfuncNoplt)) {
    if (expr == R_GOT_PC && !isAbsoluteValue(sym)) {
      expr = target->adjustRelaxExpr(type, relocatedAddr, expr);
    } else {
    if (expr != R_GOT_PC) {
      // The 0x8000 bit of r_addend of R_PPC_PLTREL24 is used to choose call
      // stub type. It should be ignored if optimized to R_PC.
      if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL)
@@ -1375,6 +1373,8 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
            type == R_HEX_GD_PLT_B22_PCREL_X ||
            type == R_HEX_GD_PLT_B32_PCREL_X)))
      expr = fromPlt(expr);
    } else if (!isAbsoluteValue(sym)) {
      expr = target->adjustGotPcExpr(type, addend, relocatedAddr);
    }
  }

+5 −0
Original line number Diff line number Diff line
@@ -155,6 +155,11 @@ RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data,
  return expr;
}

RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend,
                                    const uint8_t *data) const {
  return R_GOT_PC;
}

void TargetInfo::relaxGot(uint8_t *loc, const Relocation &rel,
                          uint64_t val) const {
  llvm_unreachable("Should not have claimed to be relaxable");
+2 −0
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ public:

  virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
                                  RelExpr expr) const;
  virtual RelExpr adjustGotPcExpr(RelType type, int64_t addend,
                                  const uint8_t *loc) const;
  virtual void relaxGot(uint8_t *loc, const Relocation &rel,
                        uint64_t val) const;
  virtual void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,