Fix a Mach-O assembler segfault for a subtraction expression with an undefined symbol.
authorKevin Enderby <enderby@apple.com>
Fri, 24 Oct 2014 22:39:40 +0000 (22:39 +0000)
committerKevin Enderby <enderby@apple.com>
Fri, 24 Oct 2014 22:39:40 +0000 (22:39 +0000)
In a Mach-O object file a relocatable expression of the form
SymbolA - SymbolB + constant is allowed when both symbols are
defined in a section.  But when either symbol is undefined it
is an error.

The code was crashing when it had an undefined symbol in this case.
And should have printed a error message using the location information
in the relocation entry.

rdar://18678402

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220599 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
test/MC/MachO/bad-darwin-x86_64-reloc-expr1.s [new file with mode: 0644]
test/MC/MachO/bad-darwin-x86_64-reloc-expr2.s [new file with mode: 0644]

index adf3fd8e4912ef2b2615dd0308a7e6743b9aaf54..5685a7fde141b07510486d3c2ea574803a53f225 100644 (file)
@@ -179,11 +179,14 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
     if (A_Base == B_Base && A_Base)
       report_fatal_error("unsupported relocation with identical base", false);
 
     if (A_Base == B_Base && A_Base)
       report_fatal_error("unsupported relocation with identical base", false);
 
-    // A subtraction expression where both symbols are undefined is a
+    // A subtraction expression where either symbol is undefined is a
     // non-relocatable expression.
     // non-relocatable expression.
-    if (A->isUndefined() && B->isUndefined())
-      report_fatal_error("unsupported relocation with subtraction expression",
-                         false);
+    if (A->isUndefined() || B->isUndefined()) {
+      StringRef Name = A->isUndefined() ? A->getName() : B->getName();
+      Asm.getContext().FatalError(Fixup.getLoc(),
+        "unsupported relocation with subtraction expression, symbol '" + 
+        Name + "' can not be undefined in a subtraction expression");
+    }
 
     Value += Writer->getSymbolAddress(&A_SD, Layout) -
       (!A_Base ? 0 : Writer->getSymbolAddress(A_Base, Layout));
 
     Value += Writer->getSymbolAddress(&A_SD, Layout) -
       (!A_Base ? 0 : Writer->getSymbolAddress(A_Base, Layout));
diff --git a/test/MC/MachO/bad-darwin-x86_64-reloc-expr1.s b/test/MC/MachO/bad-darwin-x86_64-reloc-expr1.s
new file mode 100644 (file)
index 0000000..518ae64
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple x86_64-apple-darwin10 %s -filetype=obj -o - 2> %t.err > %t
+// RUN: FileCheck --check-prefix=CHECK-ERROR < %t.err %s
+
+_Z:
+.long (_Z+4)-_b
+// CHECK-ERROR: error: unsupported relocation with subtraction expression, symbol '_b' can not be undefined in a subtraction expression
diff --git a/test/MC/MachO/bad-darwin-x86_64-reloc-expr2.s b/test/MC/MachO/bad-darwin-x86_64-reloc-expr2.s
new file mode 100644 (file)
index 0000000..3aefd87
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple x86_64-apple-darwin10 %s -filetype=obj -o - 2> %t.err > %t
+// RUN: FileCheck --check-prefix=CHECK-ERROR < %t.err %s
+
+_Z:
+.long (_a+4)-_Z
+// CHECK-ERROR: error: unsupported relocation with subtraction expression, symbol '_a' can not be undefined in a subtraction expression