From b2ad34a6ea7875c1ccfb2bee581681f7054bc4b5 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 6 Jul 2016 21:19:11 +0000 Subject: [PATCH] Add initial support for R_386_GOT32X. This adds it only for movl mov@GOT(%reg), %reg. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274678 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 2 ++ .../X86/MCTargetDesc/X86ELFObjectWriter.cpp | 25 +++++++++++++------ lib/Target/X86/MCTargetDesc/X86FixupKinds.h | 2 ++ .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 7 ++++-- .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 1 + .../MCTargetDesc/X86WinCOFFObjectWriter.cpp | 1 + test/MC/ELF/got-relaxed-i386.s | 22 ++++++++++++++++ test/MC/ELF/relocation-386.s | 4 +-- 8 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 test/MC/ELF/got-relaxed-i386.s diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 34fe3cdc5ba..5728728dc33 100644 --- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -46,6 +46,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: case X86::reloc_global_offset_table: case FK_SecRel_4: case FK_Data_4: @@ -93,6 +94,7 @@ public: {"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"reloc_signed_4byte", 0, 32, 0}, + {"reloc_signed_4byte_relax", 0, 32, 0}, {"reloc_global_offset_table", 0, 32, 0}, {"reloc_global_offset_table8", 0, 64, 0}, }; diff --git a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp index e5084f90f98..da69da51df1 100644 --- a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp @@ -58,6 +58,7 @@ static X86_64RelType getType64(unsigned Kind, case FK_Data_8: return RT64_64; case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel) return RT64_32S; return RT64_32; @@ -210,8 +211,10 @@ static X86_32RelType getType32(X86_64RelType T) { llvm_unreachable("unexpected relocation type!"); } -static unsigned getRelocType32(MCSymbolRefExpr::VariantKind Modifier, - X86_32RelType Type, bool IsPCRel) { +static unsigned getRelocType32(MCContext &Ctx, + MCSymbolRefExpr::VariantKind Modifier, + X86_32RelType Type, bool IsPCRel, + unsigned Kind) { switch (Modifier) { default: llvm_unreachable("Unimplemented"); @@ -226,7 +229,15 @@ static unsigned getRelocType32(MCSymbolRefExpr::VariantKind Modifier, } case MCSymbolRefExpr::VK_GOT: assert(Type == RT32_32); - return IsPCRel ? ELF::R_386_GOTPC : ELF::R_386_GOT32; + if (IsPCRel) + return ELF::R_386_GOTPC; + // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we + // want to maintain compatibility. + if (!Ctx.getAsmInfo()->canRelaxRelocations()) + return ELF::R_386_GOT32; + + return Kind == X86::reloc_signed_4byte_relax ? ELF::R_386_GOT32X + : ELF::R_386_GOT32; case MCSymbolRefExpr::VK_GOTOFF: assert(Type == RT32_32); assert(!IsPCRel); @@ -273,14 +284,14 @@ unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); - X86_64RelType Type = getType64(Fixup.getKind(), Modifier, IsPCRel); + unsigned Kind = Fixup.getKind(); + X86_64RelType Type = getType64(Kind, Modifier, IsPCRel); if (getEMachine() == ELF::EM_X86_64) - return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, - Fixup.getKind()); + return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind); assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) && "Unsupported ELF machine type."); - return getRelocType32(Modifier, getType32(Type), IsPCRel); + return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind); } MCObjectWriter *llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS, diff --git a/lib/Target/X86/MCTargetDesc/X86FixupKinds.h b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h index 417e04a5d94..dfdc9ec29ae 100644 --- a/lib/Target/X86/MCTargetDesc/X86FixupKinds.h +++ b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h @@ -24,6 +24,8 @@ enum Fixups { reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4 // this will be sign extended at // runtime. + reloc_signed_4byte_relax, // like reloc_signed_4byte, but + // in a relaxable instruction. reloc_global_offset_table, // 32-bit, relative to the start // of the instruction. Used only // for _GLOBAL_OFFSET_TABLE_. diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 682213908bc..96c2e81c332 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -516,8 +516,11 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, // Otherwise, emit the most general non-SIB encoding: [REG+disp32] EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(X86::reloc_signed_4byte), - CurByte, OS, Fixups); + unsigned Opcode = MI.getOpcode(); + unsigned FixupKind = Opcode == X86::MOV32rm ? X86::reloc_signed_4byte_relax + : X86::reloc_signed_4byte; + EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, + Fixups); return; } diff --git a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp index c098edec589..297926ddcfd 100644 --- a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp @@ -93,6 +93,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: case FK_Data_4: return 2; case FK_Data_8: return 3; } diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp index 90542dc2f01..0e955416839 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -80,6 +80,7 @@ unsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target, return COFF::IMAGE_REL_I386_REL32; case FK_Data_4: case X86::reloc_signed_4byte: + case X86::reloc_signed_4byte_relax: if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32) return COFF::IMAGE_REL_I386_DIR32NB; if (Modifier == MCSymbolRefExpr::VK_SECREL) diff --git a/test/MC/ELF/got-relaxed-i386.s b/test/MC/ELF/got-relaxed-i386.s new file mode 100644 index 00000000000..927066c68f2 --- /dev/null +++ b/test/MC/ELF/got-relaxed-i386.s @@ -0,0 +1,22 @@ +// RUN: llvm-mc -filetype=obj -triple i386-pc-linux %s -o - | llvm-readobj -r | FileCheck %s +// RUN: llvm-mc -filetype=obj -relax-relocations=false -triple i386-pc-linux %s -o - | llvm-readobj -r | FileCheck --check-prefix=OLD %s + + movl mov@GOT(%ebx), %eax + mull mul@GOT(%ebx) + .long long@GOT + +// CHECK: Relocations [ +// CHECK-NEXT: Section ({{.*}}) .rel.text { +// CHECK-NEXT: R_386_GOT32X mov +// CHECK-NEXT: R_386_GOT32 mul +// CHECK-NEXT: R_386_GOT32 long +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// OLD: Relocations [ +// OLD-NEXT: Section ({{.*}}) .rel.text { +// OLD-NEXT: R_386_GOT32 mov +// OLD-NEXT: R_386_GOT32 mul +// OLD-NEXT: R_386_GOT32 long +// OLD-NEXT: } +// OLD-NEXT: ] diff --git a/test/MC/ELF/relocation-386.s b/test/MC/ELF/relocation-386.s index 19efe097612..e2c4e1073ad 100644 --- a/test/MC/ELF/relocation-386.s +++ b/test/MC/ELF/relocation-386.s @@ -1,5 +1,5 @@ -// RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - | llvm-readobj -r | FileCheck %s --check-prefix=CHECK --check-prefix=I386 -// RUN: llvm-mc -filetype=obj -triple i386-pc-elfiamcu %s -o - | llvm-readobj -r | FileCheck %s --check-prefix=CHECK --check-prefix=IAMCU +// RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -relax-relocations=false -o - | llvm-readobj -r | FileCheck %s --check-prefix=CHECK --check-prefix=I386 +// RUN: llvm-mc -filetype=obj -triple i386-pc-elfiamcu %s -relax-relocations=false -o - | llvm-readobj -r | FileCheck %s --check-prefix=CHECK --check-prefix=IAMCU // Test that we produce the correct relocation types and that the relocations // correctly point to the section or the symbol. -- 2.50.1