[PATCH] D34690: [LLD][ELF] Introduce target specific inBranchRange() function

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 14 12:24:13 PDT 2017


LGTM.

I agree with the value of being precise in here.

Cheers,
Rafael

Peter Smith via Phabricator <reviews at reviews.llvm.org> writes:

> peter.smith created this revision.
> Herald added subscribers: kristof.beyls, javed.absar, emaste, aemerson.
>
> In preparation for range extension thunks introduce a function that will check whether a branch identified by a relocation type at a source address can reach a destination.
>
>       
>
> For targets where range extension thunks are not supported the function will return true as it is not expected that branches are out of range. An implementation has been provided for ARM.
>
> This is patch 7/11 of range thunks although as it is not hooked up it can be applied independently.
>
>
> https://reviews.llvm.org/D34690
>
> Files:
>   ELF/Arch/ARM.cpp
>   ELF/Target.cpp
>   ELF/Target.h
>
>
> Index: ELF/Target.h
> ===================================================================
> --- ELF/Target.h
> +++ ELF/Target.h
> @@ -51,6 +51,9 @@
>    // targeting S.
>    virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
>                            const InputFile *File, const SymbolBody &S) const;
> +  // Return true if we can reach Dst from Src with Relocation RelocType
> +  virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
> +                             uint64_t Dst) const;
>    virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
>                               const uint8_t *Loc) const = 0;
>    virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
> Index: ELF/Target.cpp
> ===================================================================
> --- ELF/Target.cpp
> +++ ELF/Target.cpp
> @@ -126,6 +126,11 @@
>    return false;
>  }
>  
> +bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
> +                               uint64_t Dst) const {
> +  return true;
> +}
> +
>  void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
>    writeGotPlt(Buf, S);
>  }
> Index: ELF/Arch/ARM.cpp
> ===================================================================
> --- ELF/Arch/ARM.cpp
> +++ ELF/Arch/ARM.cpp
> @@ -40,6 +40,8 @@
>    void addPltHeaderSymbols(InputSectionBase *ISD) const override;
>    bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
>                    const SymbolBody &S) const override;
> +  bool inBranchRange(uint32_t RelocType, uint64_t Src,
> +                     uint64_t Dst) const override;
>    void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
>  };
>  } // namespace
> @@ -222,6 +224,49 @@
>    return false;
>  }
>  
> +bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
> +  uint64_t Range;
> +  uint64_t InstrSize;
> +  switch (RelocType) {
> +  case R_ARM_PC24:
> +  case R_ARM_PLT32:
> +  case R_ARM_JUMP24:
> +  case R_ARM_CALL:
> +    Range = 0x2000000;
> +    InstrSize = 4;
> +    break;
> +  case R_ARM_THM_JUMP19:
> +    Range = 0x100000;
> +    InstrSize = 2;
> +    break;
> +  case R_ARM_THM_JUMP24:
> +  case R_ARM_THM_CALL:
> +    Range = 0x1000000;
> +    InstrSize = 2;
> +    break;
> +  default:
> +    return true;
> +  }
> +  // PC at Src is 2 instructions ahead, immediate of branch is signed
> +  if (Src > Dst)
> +    Range -= 2 * InstrSize;
> +  else
> +    Range += InstrSize;
> +
> +  if ((Dst & 0x1) == 0)
> +    // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
> +    // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
> +    // destination will be 4 byte aligned.
> +    Src &= ~0x3;
> +  else
> +    // Bit 0 == 1 denotes Thumb state, it is not part of the range
> +    Dst &= ~0x1;
> +
> +  uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;
> +
> +  return Distance <= Range;
> +}
> +
>  void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
>    switch (Type) {
>    case R_ARM_ABS32:
>
>
> Index: ELF/Target.h
> ===================================================================
> --- ELF/Target.h
> +++ ELF/Target.h
> @@ -51,6 +51,9 @@
>    // targeting S.
>    virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
>                            const InputFile *File, const SymbolBody &S) const;
> +  // Return true if we can reach Dst from Src with Relocation RelocType
> +  virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
> +                             uint64_t Dst) const;
>    virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
>                               const uint8_t *Loc) const = 0;
>    virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
> Index: ELF/Target.cpp
> ===================================================================
> --- ELF/Target.cpp
> +++ ELF/Target.cpp
> @@ -126,6 +126,11 @@
>    return false;
>  }
>  
> +bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
> +                               uint64_t Dst) const {
> +  return true;
> +}
> +
>  void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
>    writeGotPlt(Buf, S);
>  }
> Index: ELF/Arch/ARM.cpp
> ===================================================================
> --- ELF/Arch/ARM.cpp
> +++ ELF/Arch/ARM.cpp
> @@ -40,6 +40,8 @@
>    void addPltHeaderSymbols(InputSectionBase *ISD) const override;
>    bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
>                    const SymbolBody &S) const override;
> +  bool inBranchRange(uint32_t RelocType, uint64_t Src,
> +                     uint64_t Dst) const override;
>    void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
>  };
>  } // namespace
> @@ -222,6 +224,49 @@
>    return false;
>  }
>  
> +bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
> +  uint64_t Range;
> +  uint64_t InstrSize;
> +  switch (RelocType) {
> +  case R_ARM_PC24:
> +  case R_ARM_PLT32:
> +  case R_ARM_JUMP24:
> +  case R_ARM_CALL:
> +    Range = 0x2000000;
> +    InstrSize = 4;
> +    break;
> +  case R_ARM_THM_JUMP19:
> +    Range = 0x100000;
> +    InstrSize = 2;
> +    break;
> +  case R_ARM_THM_JUMP24:
> +  case R_ARM_THM_CALL:
> +    Range = 0x1000000;
> +    InstrSize = 2;
> +    break;
> +  default:
> +    return true;
> +  }
> +  // PC at Src is 2 instructions ahead, immediate of branch is signed
> +  if (Src > Dst)
> +    Range -= 2 * InstrSize;
> +  else
> +    Range += InstrSize;
> +
> +  if ((Dst & 0x1) == 0)
> +    // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
> +    // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
> +    // destination will be 4 byte aligned.
> +    Src &= ~0x3;
> +  else
> +    // Bit 0 == 1 denotes Thumb state, it is not part of the range
> +    Dst &= ~0x1;
> +
> +  uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;
> +
> +  return Distance <= Range;
> +}
> +
>  void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
>    switch (Type) {
>    case R_ARM_ABS32:


More information about the llvm-commits mailing list