[llvm] r209894 - MachO: support N_INDR aliases in assembly files.

Tim Northover tnorthover at apple.com
Fri May 30 06:23:00 PDT 2014


Author: tnorthover
Date: Fri May 30 08:22:59 2014
New Revision: 209894

URL: http://llvm.org/viewvc/llvm-project?rev=209894&view=rev
Log:
MachO: support N_INDR aliases in assembly files.

This makes LLVM create N_INDR aliases (to be resolved by the linker) when
appropriate.

rdar://problem/15125513

Added:
    llvm/trunk/test/MC/MachO/aliased-symbols.s
Modified:
    llvm/trunk/include/llvm/MC/MCMachObjectWriter.h
    llvm/trunk/include/llvm/Object/SymbolicFile.h
    llvm/trunk/lib/MC/MachObjectWriter.cpp
    llvm/trunk/lib/Object/MachOObjectFile.cpp
    llvm/trunk/test/MC/MachO/variable-exprs.s
    llvm/trunk/tools/llvm-nm/llvm-nm.cpp

Modified: llvm/trunk/include/llvm/MC/MCMachObjectWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCMachObjectWriter.h?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCMachObjectWriter.h (original)
+++ llvm/trunk/include/llvm/MC/MCMachObjectWriter.h Fri May 30 08:22:59 2014
@@ -111,6 +111,8 @@ class MachObjectWriter : public MCObject
 
   /// @}
 
+  MachSymbolData *findSymbolData(const MCSymbol &Sym);
+
 public:
   MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
                    bool _IsLittleEndian)

Modified: llvm/trunk/include/llvm/Object/SymbolicFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/SymbolicFile.h?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/SymbolicFile.h (original)
+++ llvm/trunk/include/llvm/Object/SymbolicFile.h Fri May 30 08:22:59 2014
@@ -86,6 +86,7 @@ public:
     SF_Weak = 1U << 2,           // Weak symbol
     SF_Absolute = 1U << 3,       // Absolute symbol
     SF_Common = 1U << 4,         // Symbol has common linkage
+    SF_Indirect = 1U << 5,
     SF_FormatSpecific = 1U << 5  // Specific to the object file format
                                  // (e.g. section symbols)
   };

Modified: llvm/trunk/lib/MC/MachObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MachObjectWriter.cpp?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MachObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/MachObjectWriter.cpp Fri May 30 08:22:59 2014
@@ -303,20 +303,50 @@ void MachObjectWriter::WriteDysymtabLoad
   assert(OS.tell() - Start == sizeof(MachO::dysymtab_command));
 }
 
+MachObjectWriter::MachSymbolData *
+MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
+  for (auto &Entry : LocalSymbolData)
+    if (&Entry.SymbolData->getSymbol() == &Sym)
+      return &Entry;
+
+  for (auto &Entry : ExternalSymbolData)
+    if (&Entry.SymbolData->getSymbol() == &Sym)
+      return &Entry;
+
+  for (auto &Entry : UndefinedSymbolData)
+    if (&Entry.SymbolData->getSymbol() == &Sym)
+      return &Entry;
+
+  return nullptr;
+}
+
 void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
                                   const MCAsmLayout &Layout) {
   MCSymbolData &Data = *MSD.SymbolData;
-  const MCSymbol &Symbol = Data.getSymbol();
+  const MCSymbol *Symbol = &Data.getSymbol();
+  const MCSymbol *AliasedSymbol = &Symbol->AliasedSymbol();
+  uint8_t SectionIndex = MSD.SectionIndex;
   uint8_t Type = 0;
   uint16_t Flags = Data.getFlags();
   uint64_t Address = 0;
+  bool IsAlias = Symbol != AliasedSymbol;
+
+  MachSymbolData *AliaseeInfo;
+  if (IsAlias) {
+    AliaseeInfo = findSymbolData(*AliasedSymbol);
+    if (AliaseeInfo)
+      SectionIndex = AliaseeInfo->SectionIndex;
+    Symbol = AliasedSymbol;
+  }
 
   // Set the N_TYPE bits. See <mach-o/nlist.h>.
   //
   // FIXME: Are the prebound or indirect fields possible here?
-  if (Symbol.isUndefined())
+  if (IsAlias && Symbol->isUndefined())
+    Type = MachO::N_INDR;
+  else if (Symbol->isUndefined())
     Type = MachO::N_UNDF;
-  else if (Symbol.isAbsolute())
+  else if (Symbol->isAbsolute())
     Type = MachO::N_ABS;
   else
     Type = MachO::N_SECT;
@@ -327,13 +357,15 @@ void MachObjectWriter::WriteNlist(MachSy
     Type |= MachO::N_PEXT;
 
   // Set external bit.
-  if (Data.isExternal() || Symbol.isUndefined())
+  if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
     Type |= MachO::N_EXT;
 
   // Compute the symbol address.
-  if (Symbol.isDefined()) {
+  if (IsAlias && Symbol->isUndefined())
+    Address = AliaseeInfo->StringIndex;
+  else if (Symbol->isDefined())
     Address = getSymbolAddress(&Data, Layout);
-  } else if (Data.isCommon()) {
+  else if (Data.isCommon()) {
     // Common symbols are encoded with the size in the address
     // field, and their alignment in the flags.
     Address = Data.getCommonSize();
@@ -344,21 +376,21 @@ void MachObjectWriter::WriteNlist(MachSy
       assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
       if (Log2Size > 15)
         report_fatal_error("invalid 'common' alignment '" +
-                           Twine(Align) + "' for '" + Symbol.getName() + "'",
+                           Twine(Align) + "' for '" + Symbol->getName() + "'",
                            false);
       // FIXME: Keep this mask with the SymbolFlags enumeration.
       Flags = (Flags & 0xF0FF) | (Log2Size << 8);
     }
   }
 
-  if (Layout.getAssembler().isThumbFunc(&Symbol))
+  if (Layout.getAssembler().isThumbFunc(Symbol))
     Flags |= SF_ThumbFunc;
 
   // struct nlist (12 bytes)
 
   Write32(MSD.StringIndex);
   Write8(Type);
-  Write8(MSD.SectionIndex);
+  Write8(SectionIndex);
 
   // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
   // value.

Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Fri May 30 08:22:59 2014
@@ -584,6 +584,9 @@ uint32_t MachOObjectFile::getSymbolFlags
   if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
     Result |= SymbolRef::SF_Undefined;
 
+  if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
+    Result |= SymbolRef::SF_Indirect;
+
   if (MachOType & MachO::N_STAB)
     Result |= SymbolRef::SF_FormatSpecific;
 

Added: llvm/trunk/test/MC/MachO/aliased-symbols.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/aliased-symbols.s?rev=209894&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/aliased-symbols.s (added)
+++ llvm/trunk/test/MC/MachO/aliased-symbols.s Fri May 30 08:22:59 2014
@@ -0,0 +1,115 @@
+// RUN: llvm-mc -triple thumbv7m-apple-darwin-eabi %s -filetype=obj -o %t
+// RUN:     llvm-readobj -symbols %t | FileCheck %s
+
+        .data
+        var1 = var2
+        .long var1
+        .long var2
+        .long var2 + 4
+defined_early:
+        .long 0
+
+        alias_to_early = defined_early
+        alias_to_late = defined_late
+
+defined_late:
+        .long 0
+
+        .global extern_test
+        extern_test = var2
+
+        alias_to_local = Ltmp0
+Ltmp0:
+
+// CHECK: Symbols [
+
+        // defined_early was defined. Actually has value 0xc.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: defined_early
+// CHECK-NEXT:   Type: Section (0xE)
+// CHECK-NEXT:   Section: __data (0x2)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[DEFINED_EARLY:[0-9A-F]+]]
+// CHECK-NEXT: }
+
+        // alias_to_early was an alias to defined_early. But we can resolve it.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: alias_to_early
+// CHECK-NEXT:   Type: Section (0xE)
+// CHECK-NEXT:   Section: __data (0x2)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[DEFINED_EARLY]]
+// CHECK-NEXT: }
+
+        // defined_late was defined. Just after defined_early.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: defined_late
+// CHECK-NEXT:   Type: Section (0xE)
+// CHECK-NEXT:   Section: __data (0x2)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[DEFINED_LATE:[0-9A-F]+]]
+// CHECK-NEXT: }
+
+        // alias_to_late was an alias to defined_late. But we can resolve it.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: alias_to_late
+// CHECK-NEXT:   Type: Section (0xE)
+// CHECK-NEXT:   Section: __data (0x2)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[DEFINED_LATE]]
+// CHECK-NEXT: }
+
+        // alias_to_local is an alias, but what it points to has no
+        // MachO representation. We must resolve it.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: alias_to_local (37)
+// CHECK-NEXT:   Type: Section (0xE)
+// CHECK-NEXT:   Section:  (0x0)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x14
+// CHECK-NEXT: }
+
+        // extern_test was a pure alias to the unknown "var2".
+        // N_INDR and Extern.
+// CHECK:   Name: extern_test
+// CHECK-NEXT:   Extern
+// CHECK-NEXT:   Type: Indirect (0xA)
+// CHECK-NEXT:   Section:  (0x0)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[VAR2_STRINGINDEX:[0-9a-f]+]]
+// CHECK-NEXT: }
+
+        // var1 was another alias to an unknown variable. Not extern this time.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: var1 (1)
+// CHECK-NEXT:   Type: Indirect (0xA)
+// CHECK-NEXT:   Section:  (0x0)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x[[VAR2_STRINGINDEX]]
+// CHECK-NEXT: }
+
+        // var2 was a normal undefined (extern) symbol.
+// CHECK: Symbol {
+// CHECK-NEXT:   Name: var2
+// CHECK-NEXT:   Extern
+// CHECK-NEXT:   Type: Undef (0x0)
+// CHECK-NEXT:   Section:  (0x0)
+// CHECK-NEXT:   RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT:   Flags [ (0x0)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Value: 0x0
+// CHECK-NEXT: }

Modified: llvm/trunk/test/MC/MachO/variable-exprs.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/variable-exprs.s?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/test/MC/MachO/variable-exprs.s (original)
+++ llvm/trunk/test/MC/MachO/variable-exprs.s Fri May 30 08:22:59 2014
@@ -202,10 +202,10 @@ Lt0_x = Lt0_a - Lt0_b
 // CHECK-I386:    ),
 // CHECK-I386:     # Symbol 8
 // CHECK-I386:    (('n_strx', 1)
-// CHECK-I386:     ('n_type', 0x1)
+// CHECK-I386:     ('n_type', 0xb)
 // CHECK-I386:     ('n_sect', 0)
 // CHECK-I386:     ('n_desc', 0)
-// CHECK-I386:     ('n_value', 0)
+// CHECK-I386:     ('n_value', 4)
 // CHECK-I386:     ('_string', 'd2')
 // CHECK-I386:    ),
 // CHECK-I386:     # Symbol 9
@@ -403,10 +403,10 @@ Lt0_x = Lt0_a - Lt0_b
 // CHECK-X86_64:    ),
 // CHECK-X86_64:     # Symbol 8
 // CHECK-X86_64:    (('n_strx', 1)
-// CHECK-X86_64:     ('n_type', 0x1)
+// CHECK-X86_64:     ('n_type', 0xb)
 // CHECK-X86_64:     ('n_sect', 0)
 // CHECK-X86_64:     ('n_desc', 0)
-// CHECK-X86_64:     ('n_value', 0)
+// CHECK-X86_64:     ('n_value', 4)
 // CHECK-X86_64:     ('_string', 'd2')
 // CHECK-X86_64:    ),
 // CHECK-X86_64:     # Symbol 9

Modified: llvm/trunk/tools/llvm-nm/llvm-nm.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-nm/llvm-nm.cpp?rev=209894&r1=209893&r2=209894&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-nm/llvm-nm.cpp (original)
+++ llvm/trunk/tools/llvm-nm/llvm-nm.cpp Fri May 30 08:22:59 2014
@@ -395,6 +395,8 @@ static char getSymbolNMTypeChar(MachOObj
   switch (NType & MachO::N_TYPE) {
   case MachO::N_ABS:
     return 's';
+  case MachO::N_INDR:
+    return 'i';
   case MachO::N_SECT: {
     section_iterator Sec = Obj.section_end();
     Obj.getSymbolSection(Symb, Sec);





More information about the llvm-commits mailing list