MC/Mach-O: Factor out doesSymbolRequireExternRelocation.
[oota-llvm.git] / lib / MC / MachObjectWriter.cpp
index bb8eb10a483899fab6b19d4439d4396eac98a5d7..8dd551800f8db7b83c3c717cf5522aba51876729 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCMachOSymbolFlags.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MachO.h"
@@ -58,6 +59,20 @@ static bool isFixupKindRIPRel(unsigned Kind) {
     Kind == X86::reloc_riprel_4byte_movq_load;
 }
 
+static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) {
+  // Undefined symbols are always extern.
+  if (SD->Symbol->isUndefined())
+    return true;
+
+  // References to weak definitions require external relocation entries; the
+  // definition may not always be the one in the same object file.
+  if (SD->getFlags() & SF_WeakDefinition)
+    return true;
+
+  // Otherwise, we can use an internal relocation.
+  return false;
+}
+
 namespace {
 
 class MachObjectWriterImpl {
@@ -753,9 +768,15 @@ public:
       const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
       MCSymbolData *SD = &Asm.getSymbolData(*Symbol);
 
-      if (Symbol->isUndefined()) {
+      // Check whether we need an external or internal relocation.
+      if (doesSymbolRequireExternRelocation(SD)) {
         IsExtern = 1;
         Index = SD->getIndex();
+        // For external relocations, make sure to offset the fixup value to
+        // compensate for the addend of the symbol address, if it was
+        // undefined. This occurs with weak definitions, for example.
+        if (!SD->Symbol->isUndefined())
+          FixedValue -= Layout.getSymbolAddress(SD);
         Value = 0;
       } else {
         // The index is the section ordinal (1-based).