[llvm] 31c8e11 - [MC][ARM] Emit R_ARM_BASE_PREL for _GLOBAL_OFFSET_TABLE_ expressions

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 02:39:08 PDT 2020


Author: Peter Smith
Date: 2020-04-14T10:13:21+01:00
New Revision: 31c8e118961913341e4f5c066bbdcf9b3d2109c7

URL: https://github.com/llvm/llvm-project/commit/31c8e118961913341e4f5c066bbdcf9b3d2109c7
DIFF: https://github.com/llvm/llvm-project/commit/31c8e118961913341e4f5c066bbdcf9b3d2109c7.diff

LOG: [MC][ARM] Emit R_ARM_BASE_PREL for _GLOBAL_OFFSET_TABLE_ expressions

The _GLOBAL_OFFSET_TABLE_ in SysVr4 ELF is conventionally the base of the
.got or .got.prel sections. Expressions such as _GLOBAL_OFFSET_TABLE_
- (.L1 +8) are used in assembler code to calculate offsets into the .got.
At present MC outputs a R_ARM_REL32 with respect to the
_GLOBAL_OFFSET_TABLE_ symbol, whereas gas outputs a R_ARM_BASE_PREL
relocation with respect to the _GLOBAL_OFFSET_TABLE_ symbol. While both are
correct the R_ARM_REL32 depends on the value of the _GLOBAL_OFFSET_TABLE_
symbol, wheras te R_ARM_BASE_PREL relocation is idependent of the symbol.
The R_ARM_BASE_PREL is therefore slightly more robust to linker's that may
not follow the conventional placement of _GLOBAL_OFFSET_TABLE_; for example
LLD for some time defined _GLOBAL_OFFSET_TABLE_ to 0.

Differential Revision: https://reviews.llvm.org/D46319

Added: 
    

Modified: 
    llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
    llvm/test/MC/ARM/symbol-variants.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index 84cbd4a42686..f803671ac976 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -93,8 +93,15 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
       switch (Modifier) {
       default:
         llvm_unreachable("Unsupported Modifier");
-      case MCSymbolRefExpr::VK_None:
+      case MCSymbolRefExpr::VK_None: {
+        if (const MCSymbolRefExpr *SymRef = Target.getSymA()) {
+          // For GNU AS compatibility expressions such as
+          // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.
+          if (SymRef->getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_")
+            return ELF::R_ARM_BASE_PREL;
+        }
         return ELF::R_ARM_REL32;
+      }
       case MCSymbolRefExpr::VK_GOTTPOFF:
         return ELF::R_ARM_TLS_IE32;
       case MCSymbolRefExpr::VK_ARM_GOT_PREL:

diff  --git a/llvm/test/MC/ARM/symbol-variants.s b/llvm/test/MC/ARM/symbol-variants.s
index 6ddf810cf033..55ff9e37833f 100644
--- a/llvm/test/MC/ARM/symbol-variants.s
+++ b/llvm/test/MC/ARM/symbol-variants.s
@@ -96,8 +96,16 @@ bl f05(plt)
 @CHECK: 70 R_ARM_TLS_LDM32 f28
 @CHECK: 74 R_ARM_TLS_LDM32 f29
 
+@ relative
+.word f30 - (.Lsym+8)
+ at CHECK: 78 R_ARM_REL32 f30
+
+@ _GLOBAL_OFFSET_TABLE_ relative
+.word _GLOBAL_OFFSET_TABLE_ - (.Lsym+8)
+ at CHECK: 7c R_ARM_BASE_PREL _GLOBAL_OFFSET_TABLE_
+
 @ got_prel
-.word	f30(GOT_PREL) + (. - .Lsym)
-	ldr r3, =f31(GOT_PREL)
-@ CHECK: 78 R_ARM_GOT_PREL f30
-@ CHECK: 80 R_ARM_GOT_PREL f31
+.word   f31(GOT_PREL) + (. - .Lsym)
+        ldr r3, =f32(GOT_PREL)
+ at CHECK: 80 R_ARM_GOT_PREL f31
+ at CHECK: 88 R_ARM_GOT_PREL f32


        


More information about the llvm-commits mailing list