OSDN Git Service

Add initial support for R_386_GOT32X.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 6 Jul 2016 21:19:11 +0000 (21:19 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 6 Jul 2016 21:19:11 +0000 (21:19 +0000)
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
lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
lib/Target/X86/MCTargetDesc/X86FixupKinds.h
lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
test/MC/ELF/got-relaxed-i386.s [new file with mode: 0644]
test/MC/ELF/relocation-386.s

index 34fe3cd..5728728 100644 (file)
@@ -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},
     };
index e5084f9..da69da5 100644 (file)
@@ -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,
index 417e04a..dfdc9ec 100644 (file)
@@ -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_.
index 6822139..96c2e81 100644 (file)
@@ -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;
   }
 
index c098ede..297926d 100644 (file)
@@ -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;
   }
index 90542dc..0e95541 100644 (file)
@@ -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 (file)
index 0000000..927066c
--- /dev/null
@@ -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: ]
index 19efe09..e2c4e10 100644 (file)
@@ -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.