[PATCH] x86_64: Fix section relocation for SECTIONREL32 with immediate offset

Kai Nacke kai at redstar.de
Tue Apr 23 13:53:49 PDT 2013


Hi!

The tls code for x86_64 generates code like
     movq    values at SECREL32(%rax), %rcx
and
     movq    values at SECREL32+8(%rax), %rax

The first relocation is translated to relocation type 
IMAGE_REL_AMD64_SECREL but the second one to IMAGE_REL_AMD64_ADDR32. The 
latter relocation type requires the specification of linker flag 
/LARGEADDRESSAWARE:NO. This patch changes the relocation type to 
IMAGE_REL_AMD64_SECREL, avoiding the linker flag.

The attached test case is a .ll file because llvm-mc does not support 
@SECTIONREL32.

Regards
Kai
-------------- next part --------------
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 182bec1..016af71 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -237,6 +237,14 @@ StartsWithGlobalOffsetTable(const MCExpr *Expr) {
   return GOT_Normal;
 }
 
+static bool HasSecRelSymbolRef(const MCExpr *Expr) {
+  if (Expr->getKind() == MCExpr::SymbolRef) {
+    const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
+    return Ref->getKind() == MCSymbolRefExpr::VK_SECREL;
+  }
+  return false;
+}
+
 void X86MCCodeEmitter::
 EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size,
               MCFixupKind FixupKind, unsigned &CurByte, raw_ostream &OS,
@@ -268,8 +276,13 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size,
       if (Kind == GOT_Normal)
         ImmOffset = CurByte;
     } else if (Expr->getKind() == MCExpr::SymbolRef) {
-      const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
-      if (Ref->getKind() == MCSymbolRefExpr::VK_SECREL) {
+      if (HasSecRelSymbolRef(Expr)) {
+        FixupKind = MCFixupKind(FK_SecRel_4);
+      }
+    } else if (Expr->getKind() == MCExpr::Binary) {
+      const MCBinaryExpr *Bin = static_cast<const MCBinaryExpr*>(Expr);
+      if (HasSecRelSymbolRef(Bin->getLHS())
+          || HasSecRelSymbolRef(Bin->getRHS())) {
         FixupKind = MCFixupKind(FK_SecRel_4);
       }
     }
diff --git a/test/MC/X86/x86_64-secrel.ll b/test/MC/X86/x86_64-secrel.ll
new file mode 100644
index 0000000..10e3bf9
--- /dev/null
+++ b/test/MC/X86/x86_64-secrel.ll
@@ -0,0 +1,25 @@
+; RUN: llc -O0 -filetype=obj -mtriple=x86_64-pc-win32 %s -o=- | llvm-readobj -r | FileCheck %s
+
+; Uses a .ll file because llvm-mc does not understand the @SEGREL32 syntax.
+
+ at values = thread_local global { i64, i64 } { i64 1, i64 0 }
+
+define i32 @main(i32 %argc, i8** %argv) {
+entry:
+  %len = alloca i64, align 8
+  %val = alloca i64, align 8
+  %lenadr = getelementptr { i64, i64 }* @values, i32 0, i32 0
+  %tmp1 = load i64* %lenadr
+  store i64 %tmp1, i64* %len
+  %valadr = getelementptr { i64, i64 }* @values, i32 0, i32 1
+  %tmp2 = load i64* %valadr
+  store i64 %tmp2, i64* %val
+  ret i32 0
+}
+
+; CHECK:      Relocations [
+; CHECK-NEXT:   Section (1) .text {
+; CHECK-NEXT:     0x6 IMAGE_REL_AMD64_REL32 _tls_index
+; CHECK-NEXT:     0x1A IMAGE_REL_AMD64_SECREL values
+; CHECK-NEXT:     0x26 IMAGE_REL_AMD64_SECREL values
+; CHECK-NEXT:   }


More information about the llvm-commits mailing list