From 31c8e118961913341e4f5c066bbdcf9b3d2109c7 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Mon, 13 Apr 2020 08:55:07 +0100 Subject: [PATCH] [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 --- llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 9 ++++++++- llvm/test/MC/ARM/symbol-variants.s | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index 84cbd4a..f803671 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 6ddf810..55ff9e3 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) +@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 -- 2.7.4