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
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:
@CHECK: 70 R_ARM_TLS_LDM32 f28
@CHECK: 74 R_ARM_TLS_LDM32 f29
+@ relative
+.word f30 - (.Lsym+8)
+@CHECK: 78 R_ARM_REL32 f30
+
+@ _GLOBAL_OFFSET_TABLE_ relative
+.word _GLOBAL_OFFSET_TABLE_ - (.Lsym+8)
+@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)
+@CHECK: 80 R_ARM_GOT_PREL f31
+@CHECK: 88 R_ARM_GOT_PREL f32