[llvm-commits] [llvm] r80089 - in /llvm/trunk: include/llvm/MC/MCAssembler.h lib/MC/MCAssembler.cpp test/MC/MachO/reloc.s

Daniel Dunbar daniel at zuster.org
Wed Aug 26 06:58:10 PDT 2009


Author: ddunbar
Date: Wed Aug 26 08:58:10 2009
New Revision: 80089

URL: http://llvm.org/viewvc/llvm-project?rev=80089&view=rev
Log:
llvm-mc/Mach-O: Add support for relocations.
 - I haven't really tried to find the "right" way to store the fixups or apply
   them, yet. This works, but isn't particularly elegant or fast.

 - Still no evaluation support, so we don't actually ever not turn a fixup into
   a relocation entry.

Added:
    llvm/trunk/test/MC/MachO/reloc.s
Modified:
    llvm/trunk/include/llvm/MC/MCAssembler.h
    llvm/trunk/lib/MC/MCAssembler.cpp

Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=80089&r1=80088&r2=80089&view=diff

==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Wed Aug 26 08:58:10 2009
@@ -246,11 +246,45 @@
   void operator=(const MCSectionData&); // DO NOT IMPLEMENT
 
 public:
+  /// Fixup - Represent a fixed size region of bytes inside some fragment which
+  /// needs to be rewritten. This region will either be rewritten by the
+  /// assembler or cause a relocation entry to be generated.
+  struct Fixup {
+    /// Fragment - The fragment containing the fixup.
+    MCFragment *Fragment;
+    
+    /// Offset - The offset inside the fragment which needs to be rewritten.
+    uint64_t Offset;
+
+    /// Value - The expression to eventually write into the fragment.
+    //
+    // FIXME: We could probably get away with requiring the client to pass in an
+    // owned reference whose lifetime extends past that of the fixup.
+    MCValue Value;
+
+    /// Size - The fixup size.
+    unsigned Size;
+
+    /// FixedValue - The value to replace the fix up by.
+    //
+    // FIXME: This should not be here.
+    uint64_t FixedValue;
+
+  public:
+    Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCValue &_Value, 
+          unsigned _Size) 
+      : Fragment(&_Fragment), Offset(_Offset), Value(_Value), Size(_Size),
+        FixedValue(0) {}
+  };
+
   typedef iplist<MCFragment> FragmentListType;
 
   typedef FragmentListType::const_iterator const_iterator;
   typedef FragmentListType::iterator iterator;
 
+  typedef std::vector<Fixup>::const_iterator const_fixup_iterator;
+  typedef std::vector<Fixup>::iterator fixup_iterator;
+
 private:
   iplist<MCFragment> Fragments;
   const MCSection &Section;
@@ -274,6 +308,12 @@
   /// initialized.
   uint64_t FileSize;
 
+  /// LastFixupLookup - Cache for the last looked up fixup.
+  mutable unsigned LastFixupLookup;
+
+  /// Fixups - The list of fixups in this section.
+  std::vector<Fixup> Fixups;
+  
   /// @}
 
 public:    
@@ -303,11 +343,39 @@
   bool empty() const { return Fragments.empty(); }
 
   /// @}
+  /// @name Fixup Access
+  /// @{
+
+  std::vector<Fixup> &getFixups() {
+    return Fixups;
+  }
+
+  fixup_iterator fixup_begin() {
+    return Fixups.begin();
+  }
+
+  fixup_iterator fixup_end() {
+    return Fixups.end();
+  }
+
+  size_t fixup_size() const { return Fixups.size(); }
+
+  /// @}
   /// @name Assembler Backend Support
   /// @{
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
+  /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
+  /// Offset.
+  ///
+  /// If multiple fixups exist for the same fragment and offset it is undefined
+  /// which one is returned.
+  //
+  // FIXME: This isn't horribly slow in practice, but there are much nicer
+  // solutions to applying the fixups.
+  const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const;
+
   uint64_t getAddress() const { 
     assert(Address != ~UINT64_C(0) && "Address not set!");
     return Address;

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=80089&r1=80088&r2=80089&view=diff

==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Wed Aug 26 08:58:10 2009
@@ -42,6 +42,7 @@
   static const unsigned SymtabLoadCommandSize = 24;
   static const unsigned DysymtabLoadCommandSize = 80;
   static const unsigned Nlist32Size = 12;
+  static const unsigned RelocationInfoSize = 8;
 
   enum HeaderFileType {
     HFT_Object = 0x1
@@ -77,6 +78,19 @@
     ISF_Absolute = 0x40000000
   };
 
+  /// RelocationFlags - Special flags for addresses.
+  enum RelocationFlags {
+    RF_Scattered = 0x80000000
+  };
+
+  enum RelocationInfoType {
+    RIT_Vanilla             = 0,
+    RIT_Pair                = 1,
+    RIT_Difference          = 2,
+    RIT_PreboundLazyPointer = 3,
+    RIT_LocalDifference     = 4
+  };
+
   /// MachSymbolData - Helper struct for containing some precomputed information
   /// on symbols.
   struct MachSymbolData {
@@ -205,7 +219,8 @@
     assert(OS.tell() - Start == SegmentLoadCommand32Size);
   }
 
-  void WriteSection32(const MCSectionData &SD, uint64_t FileOffset) {
+  void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
+                      uint64_t RelocationsStart, unsigned NumRelocations) {
     // struct section (68 bytes)
 
     uint64_t Start = OS.tell();
@@ -222,8 +237,8 @@
 
     assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
     Write32(Log2_32(SD.getAlignment()));
-    Write32(0); // file offset of relocation entries
-    Write32(0); // number of relocation entrions
+    Write32(NumRelocations ? RelocationsStart : 0);
+    Write32(NumRelocations);
     Write32(Section.getTypeAndAttributes());
     Write32(0); // reserved1
     Write32(Section.getStubSize()); // reserved2
@@ -332,6 +347,126 @@
     Write32(Address);
   }
 
+  struct MachRelocationEntry {
+    uint32_t Word0;
+    uint32_t Word1;
+  };
+  void ComputeScatteredRelocationInfo(MCAssembler &Asm,
+                                      MCSectionData::Fixup &Fixup,
+                             DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
+                                     std::vector<MachRelocationEntry> &Relocs) {
+    uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+    unsigned IsPCRel = 0;
+    unsigned Type = RIT_Vanilla;
+
+    // See <reloc.h>.
+
+    const MCSymbol *A = Fixup.Value.getSymA();
+    MCSymbolData *SD = SymbolMap.lookup(A);
+    uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
+    uint32_t Value2 = 0;
+
+    if (const MCSymbol *B = Fixup.Value.getSymB()) {
+      Type = RIT_LocalDifference;
+
+      MCSymbolData *SD = SymbolMap.lookup(B);
+      Value2 = SD->getFragment()->getAddress() + SD->getOffset();
+    }
+
+    unsigned Log2Size = Log2_32(Fixup.Size);
+    assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
+
+    // The value which goes in the fixup is current value of the expression.
+    Fixup.FixedValue = Value - Value2 + Fixup.Value.getConstant();
+
+    MachRelocationEntry MRE;
+    MRE.Word0 = ((Address   <<  0) |
+                 (Type      << 24) |
+                 (Log2Size  << 28) |
+                 (IsPCRel   << 30) |
+                 RF_Scattered);
+    MRE.Word1 = Value;
+    Relocs.push_back(MRE);
+
+    if (Type == RIT_LocalDifference) {
+      Type = RIT_Pair;
+
+      MachRelocationEntry MRE;
+      MRE.Word0 = ((0         <<  0) |
+                   (Type      << 24) |
+                   (Log2Size  << 28) |
+                   (0   << 30) |
+                   RF_Scattered);
+      MRE.Word1 = Value2;
+      Relocs.push_back(MRE);
+    }
+  }
+
+  void ComputeRelocationInfo(MCAssembler &Asm,
+                             MCSectionData::Fixup &Fixup,
+                             DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
+                             std::vector<MachRelocationEntry> &Relocs) {
+    // If this is a local symbol plus an offset or a difference, then we need a
+    // scattered relocation entry.
+    if (Fixup.Value.getSymB()) // a - b
+      return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
+    if (Fixup.Value.getSymA() && Fixup.Value.getConstant())
+      if (!Fixup.Value.getSymA()->isUndefined())
+        return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
+        
+    // See <reloc.h>.
+    uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+    uint32_t Value = 0;
+    unsigned Index = 0;
+    unsigned IsPCRel = 0;
+    unsigned IsExtern = 0;
+    unsigned Type = 0;
+
+    if (Fixup.Value.isAbsolute()) { // constant
+      // SymbolNum of 0 indicates the absolute section.
+      Type = RIT_Vanilla;
+      Value = 0;
+      llvm_unreachable("FIXME: Not yet implemented!");
+    } else {
+      const MCSymbol *Symbol = Fixup.Value.getSymA();
+      MCSymbolData *SD = SymbolMap.lookup(Symbol);
+      
+      if (Symbol->isUndefined()) {
+        IsExtern = 1;
+        Index = SD->getIndex();
+        Value = 0;
+      } else {
+        // The index is the section ordinal.
+        //
+        // FIXME: O(N)
+        Index = 1;
+        for (MCAssembler::iterator it = Asm.begin(),
+               ie = Asm.end(); it != ie; ++it, ++Index)
+          if (&*it == SD->getFragment()->getParent())
+            break;
+        Value = SD->getFragment()->getAddress() + SD->getOffset();
+      }
+
+      Type = RIT_Vanilla;
+    }
+
+    // The value which goes in the fixup is current value of the expression.
+    Fixup.FixedValue = Value + Fixup.Value.getConstant();
+
+    unsigned Log2Size = Log2_32(Fixup.Size);
+    assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
+
+    // struct relocation_info (8 bytes)
+    MachRelocationEntry MRE;
+    MRE.Word0 = Address;
+    MRE.Word1 = ((Index     <<  0) |
+                 (IsPCRel   << 24) |
+                 (Log2Size  << 25) |
+                 (IsExtern  << 27) |
+                 (Type      << 28));
+    Relocs.push_back(MRE);
+  }
+  
   void BindIndirectSymbols(MCAssembler &Asm,
                            DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap) {
     // This is the point where 'as' creates actual symbols for indirect symbols
@@ -543,9 +678,31 @@
     WriteSegmentLoadCommand32(NumSections, SectionDataStart, SectionDataSize);
   
     // ... and then the section headers.
-    for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
-      WriteSection32(*it, SectionDataStart + it->getAddress());
-
+    // 
+    // We also compute the section relocations while we do this. Note that
+    // compute relocation info will also update the fixup to have the correct
+    // value; this will be overwrite the appropriate data in the fragment when
+    // it is written.
+    std::vector<MachRelocationEntry> RelocInfos;
+    uint64_t RelocTableEnd = SectionDataEnd;
+    for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
+         ++it) {
+      MCSectionData &SD = *it;
+
+      // The assembler writes relocations in the reverse order they were seen.
+      //
+      // FIXME: It is probably more complicated than this.
+      unsigned NumRelocsStart = RelocInfos.size();
+      for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
+        ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
+                              RelocInfos);
+
+      unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
+      uint64_t SectionStart = SectionDataStart + SD.getAddress();
+      WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs);
+      RelocTableEnd += NumRelocs * RelocationInfoSize;
+    }
+    
     // Write the symbol table load command, if used.
     if (NumSymbols) {
       unsigned FirstLocalSymbol = 0;
@@ -562,10 +719,10 @@
 
       // If used, the indirect symbols are written after the section data.
       if (NumIndirectSymbols)
-        IndirectSymbolOffset = SectionDataEnd;
+        IndirectSymbolOffset = RelocTableEnd;
 
       // The symbol table is written after the indirect symbol data.
-      uint64_t SymbolTableOffset = SectionDataEnd + IndirectSymbolSize;
+      uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
 
       // The string table is written after symbol table.
       uint64_t StringTableOffset =
@@ -583,6 +740,12 @@
     for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
       WriteFileData(OS, *it, *this);
 
+    // Write the relocation entries.
+    for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) {
+      Write32(RelocInfos[i].Word0);
+      Write32(RelocInfos[i].Word1);
+    }
+
     // Write the symbol table data, if used.
     if (NumSymbols) {
       // Write the indirect symbol entries.
@@ -657,12 +820,35 @@
     Alignment(1),
     Address(~UINT64_C(0)),
     Size(~UINT64_C(0)),
-    FileSize(~UINT64_C(0))
+    FileSize(~UINT64_C(0)),
+    LastFixupLookup(~0)
 {
   if (A)
     A->getSectionList().push_back(this);
 }
 
+const MCSectionData::Fixup *
+MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const {
+  // Use a one level cache to turn the common case of accessing the fixups in
+  // order into O(1) instead of O(N).
+  unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
+  if (i >= End)
+    i = 0;
+  while (Count--) {
+    const Fixup &F = Fixups[i];
+    if (F.Fragment == Fragment && F.Offset == Offset) {
+      LastFixupLookup = i;
+      return &F;
+    }
+
+    ++i;
+    if (i == End)
+      i = 0;
+  }
+
+  return 0;
+}
+                                                       
 /* *** */
 
 MCSymbolData::MCSymbolData() : Symbol(*(MCSymbol*)0) {}
@@ -705,10 +891,27 @@
     }
 
     case MCFragment::FT_Data:
-    case MCFragment::FT_Fill:
       F.setFileSize(F.getMaxFileSize());
       break;
 
+    case MCFragment::FT_Fill: {
+      MCFillFragment &FF = cast<MCFillFragment>(F);
+
+      F.setFileSize(F.getMaxFileSize());
+
+      // If the fill value is constant, thats it.
+      if (FF.getValue().isAbsolute())
+        break;
+
+      // Otherwise, add fixups for the values.
+      for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
+        MCSectionData::Fixup Fix(F, i * FF.getValueSize(),
+                                 FF.getValue(),FF.getValueSize());
+        SD.getFixups().push_back(Fix);
+      }
+      break;
+    }
+
     case MCFragment::FT_Org: {
       MCOrgFragment &OF = cast<MCOrgFragment>(F);
 
@@ -778,11 +981,20 @@
   case MCFragment::FT_Fill: {
     MCFillFragment &FF = cast<MCFillFragment>(F);
 
+    int64_t Value = 0;
     if (!FF.getValue().isAbsolute())
-      llvm_unreachable("FIXME: Not yet implemented!");
-    int64_t Value = FF.getValue().getConstant();
-
+      Value = FF.getValue().getConstant();
     for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
+      if (!FF.getValue().isAbsolute()) {
+        // Find the fixup.
+        //
+        // FIXME: Find a better way to write in the fixes.
+        const MCSectionData::Fixup *Fixup =
+          F.getParent()->LookupFixup(&F, i * FF.getValueSize());
+        assert(Fixup && "Missing fixup for fill value!");
+        Value = Fixup->FixedValue;
+      }
+
       switch (FF.getValueSize()) {
       default:
         assert(0 && "Invalid size!");

Added: llvm/trunk/test/MC/MachO/reloc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/reloc.s?rev=80089&view=auto

==============================================================================
--- llvm/trunk/test/MC/MachO/reloc.s (added)
+++ llvm/trunk/test/MC/MachO/reloc.s Wed Aug 26 08:58:10 2009
@@ -0,0 +1,227 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
+
+        .data
+        .long undef
+        .long (undef + 4)
+
+        .globl local_a_ext
+local_a_ext:
+        .long local_a_ext
+
+local_a:
+        .long 0
+local_a_elt:      
+        .long 0
+local_b:
+        .long local_b - local_c + 245
+        .long 0
+local_c:
+        .long 0
+
+
+        .long local_a_elt + 1
+        .long local_a_elt + 10
+        .short local_a_elt + 20
+        .byte local_a_elt + 89
+
+        .const
+
+        .long
+bar:    
+        .long local_a_elt - bar + 33
+
+// CHECK: ('cputype', 7)
+// CHECK: ('cpusubtype', 3)
+// CHECK: ('filetype', 1)
+// CHECK: ('num_load_commands', 1)
+// CHECK: ('load_commands_size', 364)
+// CHECK: ('flag', 0)
+// CHECK: ('load_commands', [
+// CHECK:   # Load Command 0
+// CHECK:  (('command', 1)
+// CHECK:   ('size', 260)
+// CHECK:   ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:   ('vm_addr', 0)
+// CHECK:   ('vm_size', 47)
+// CHECK:   ('file_offset', 392)
+// CHECK:   ('file_size', 47)
+// CHECK:   ('maxprot', 7)
+// CHECK:   ('initprot', 7)
+// CHECK:   ('num_sections', 3)
+// CHECK:   ('flags', 0)
+// CHECK:   ('sections', [
+// CHECK:     # Section 0
+// CHECK:    (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('address', 0)
+// CHECK:     ('size', 0)
+// CHECK:     ('offset', 392)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 0)
+// CHECK:     ('num_reloc', 0)
+// CHECK:     ('flags', 0x80000000)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// CHECK:   ('_relocations', [
+// CHECK:   ])
+// CHECK:   ('_section_data', '')
+// CHECK:     # Section 1
+// CHECK:    (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('address', 0)
+// CHECK:     ('size', 43)
+// CHECK:     ('offset', 392)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 440)
+// CHECK:     ('num_reloc', 9)
+// CHECK:     ('flags', 0x0)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// CHECK:   ('_relocations', [
+// CHECK:     # Relocation 0
+// CHECK:     (('word-0', 0x8000002a),
+// CHECK:      ('word-1', 0x10)),
+// CHECK:     # Relocation 1
+// CHECK:     (('word-0', 0x90000028),
+// CHECK:      ('word-1', 0x10)),
+// CHECK:     # Relocation 2
+// CHECK:     (('word-0', 0xa0000024),
+// CHECK:      ('word-1', 0x10)),
+// CHECK:     # Relocation 3
+// CHECK:     (('word-0', 0xa0000020),
+// CHECK:      ('word-1', 0x10)),
+// CHECK:     # Relocation 4
+// CHECK:     (('word-0', 0xa4000014),
+// CHECK:      ('word-1', 0x14)),
+// CHECK:     # Relocation 5
+// CHECK:     (('word-0', 0xa1000000),
+// CHECK:      ('word-1', 0x1c)),
+// CHECK:     # Relocation 6
+// CHECK:     (('word-0', 0x8),
+// CHECK:      ('word-1', 0x4000002)),
+// CHECK:     # Relocation 7
+// CHECK:     (('word-0', 0x4),
+// CHECK:      ('word-1', 0xc000006)),
+// CHECK:     # Relocation 8
+// CHECK:     (('word-0', 0x0),
+// CHECK:      ('word-1', 0xc000006)),
+// CHECK:   ])
+// CHECK:   ('_section_data', '\x00\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x1a\x00\x00\x00$\x00i')
+// CHECK:     # Section 2
+// CHECK:    (('section_name', '__const\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('address', 43)
+// CHECK:     ('size', 4)
+// CHECK:     ('offset', 435)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 512)
+// CHECK:     ('num_reloc', 2)
+// CHECK:     ('flags', 0x0)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// CHECK:   ('_relocations', [
+// CHECK:     # Relocation 0
+// CHECK:     (('word-0', 0xa4000000),
+// CHECK:      ('word-1', 0x10)),
+// CHECK:     # Relocation 1
+// CHECK:     (('word-0', 0xa1000000),
+// CHECK:      ('word-1', 0x2b)),
+// CHECK:   ])
+// CHECK:   ('_section_data', '\x06\x00\x00\x00')
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 1
+// CHECK:  (('command', 2)
+// CHECK:   ('size', 24)
+// CHECK:   ('symoff', 528)
+// CHECK:   ('nsyms', 7)
+// CHECK:   ('stroff', 612)
+// CHECK:   ('strsize', 60)
+// CHECK:   ('_string_data', '\x00undef\x00local_a_ext\x00local_a\x00local_a_elt\x00local_b\x00local_c\x00bar\x00\x00')
+// CHECK:   ('_symbols', [
+// CHECK:     # Symbol 0
+// CHECK:    (('n_strx', 19)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 12)
+// CHECK:     ('_string', 'local_a')
+// CHECK:    ),
+// CHECK:     # Symbol 1
+// CHECK:    (('n_strx', 27)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 16)
+// CHECK:     ('_string', 'local_a_elt')
+// CHECK:    ),
+// CHECK:     # Symbol 2
+// CHECK:    (('n_strx', 39)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 20)
+// CHECK:     ('_string', 'local_b')
+// CHECK:    ),
+// CHECK:     # Symbol 3
+// CHECK:    (('n_strx', 47)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 28)
+// CHECK:     ('_string', 'local_c')
+// CHECK:    ),
+// CHECK:     # Symbol 4
+// CHECK:    (('n_strx', 55)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 3)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 43)
+// CHECK:     ('_string', 'bar')
+// CHECK:    ),
+// CHECK:     # Symbol 5
+// CHECK:    (('n_strx', 7)
+// CHECK:     ('n_type', 0xf)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 8)
+// CHECK:     ('_string', 'local_a_ext')
+// CHECK:    ),
+// CHECK:     # Symbol 6
+// CHECK:    (('n_strx', 1)
+// CHECK:     ('n_type', 0x1)
+// CHECK:     ('n_sect', 0)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 0)
+// CHECK:     ('_string', 'undef')
+// CHECK:    ),
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 2
+// CHECK:  (('command', 11)
+// CHECK:   ('size', 80)
+// CHECK:   ('ilocalsym', 0)
+// CHECK:   ('nlocalsym', 5)
+// CHECK:   ('iextdefsym', 5)
+// CHECK:   ('nextdefsym', 1)
+// CHECK:   ('iundefsym', 6)
+// CHECK:   ('nundefsym', 1)
+// CHECK:   ('tocoff', 0)
+// CHECK:   ('ntoc', 0)
+// CHECK:   ('modtaboff', 0)
+// CHECK:   ('nmodtab', 0)
+// CHECK:   ('extrefsymoff', 0)
+// CHECK:   ('nextrefsyms', 0)
+// CHECK:   ('indirectsymoff', 0)
+// CHECK:   ('nindirectsyms', 0)
+// CHECK:   ('extreloff', 0)
+// CHECK:   ('nextrel', 0)
+// CHECK:   ('locreloff', 0)
+// CHECK:   ('nlocrel', 0)
+// CHECK:   ('_indirect_symbols', [
+// CHECK:   ])
+// CHECK:  ),
+// CHECK: ])





More information about the llvm-commits mailing list