llvm-mc/Mach-O: Set addresses for symbols.
authorDaniel Dunbar <daniel@zuster.org>
Wed, 26 Aug 2009 02:48:04 +0000 (02:48 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 26 Aug 2009 02:48:04 +0000 (02:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80065 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAssembler.h
lib/MC/MCAssembler.cpp
lib/MC/MCMachOStreamer.cpp
test/MC/MachO/symbol-indirect.s
test/MC/MachO/values.s [new file with mode: 0644]

index b5ee5017cc95d7ade55be5183f4e454f1e182c31..ce9dca1ae12593bf4289209325759f3798e6a27a 100644 (file)
@@ -39,6 +39,9 @@ public:
 private:
   FragmentType Kind;
 
+  /// Parent - The data for the section this fragment is in.
+  MCSectionData *Parent;
+
   /// @name Assembler Backend Data
   /// @{
   //
@@ -54,7 +57,7 @@ private:
   /// @}
 
 protected:
-  MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
+  MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0);
 
 public:
   // Only for sentinel.
@@ -63,6 +66,9 @@ public:
 
   FragmentType getKind() const { return Kind; }
 
+  MCSectionData *getParent() const { return Parent; }
+  void setParent(MCSectionData *Value) { Parent = Value; }
+
   // FIXME: This should be abstract, fix sentinel.
   virtual uint64_t getMaxFileSize() const {
     assert(0 && "Invalid getMaxFileSize call!");
@@ -74,6 +80,8 @@ public:
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
+  uint64_t getAddress() const;
+
   unsigned getFileSize() const { 
     assert(FileSize != ~UINT64_C(0) && "File size not set!");
     return FileSize;
@@ -255,6 +263,10 @@ private:
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
+  /// Address - The computed address of this section. This is ~0 until
+  /// initialized.
+  uint64_t Address;
+
   /// FileSize - The size of this section in the object file. This is ~0 until
   /// initialized.
   uint64_t FileSize;
@@ -293,6 +305,12 @@ public:
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
+  unsigned getAddress() const { 
+    assert(Address != ~UINT64_C(0) && "Address not set!");
+    return Address;
+  }
+  void setAddress(uint64_t Value) { Address = Value; }
+
   unsigned getFileSize() const { 
     assert(FileSize != ~UINT64_C(0) && "File size not set!");
     return FileSize;
index fc5d31ca50bee27262d45954b36490c990e8dd46..13c193275cb8aaa80df59ce5931996724cf57107 100644 (file)
@@ -216,7 +216,7 @@ public:
       static_cast<const MCSectionMachO&>(SD.getSection());
     WriteString(Section.getSectionName(), 16);
     WriteString(Section.getSegmentName(), 16);
-    Write32(0); // address
+    Write32(SD.getAddress()); // address
     Write32(SD.getFileSize()); // size
     Write32(FileOffset);
 
@@ -287,7 +287,8 @@ public:
   }
 
   void WriteNlist32(MachSymbolData &MSD) {
-    MCSymbol &Symbol = MSD.SymbolData->getSymbol();
+    MCSymbolData &Data = *MSD.SymbolData;
+    MCSymbol &Symbol = Data.getSymbol();
     uint8_t Type = 0;
 
     // Set the N_TYPE bits. See <mach-o/nlist.h>.
@@ -302,11 +303,11 @@ public:
 
     // FIXME: Set STAB bits.
 
-    if (MSD.SymbolData->isPrivateExtern())
+    if (Data.isPrivateExtern())
       Type |= STF_PrivateExtern;
 
     // Set external bit.
-    if (MSD.SymbolData->isExternal() || Symbol.isUndefined())
+    if (Data.isExternal() || Symbol.isUndefined())
       Type |= STF_External;
 
     // struct nlist (12 bytes)
@@ -317,9 +318,18 @@ public:
     
     // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
     // value.
-    Write16(MSD.SymbolData->getFlags() & 0xFFFF);
+    Write16(Data.getFlags() & 0xFFFF);
 
-    Write32(0); // FIXME: Value
+    // Write the symbol address.
+    uint32_t Address = 0;
+    if (Symbol.isDefined()) {
+      if (Symbol.isAbsolute()) {
+        llvm_unreachable("FIXME: Not yet implemented!");
+      } else {
+        Address = Data.getFragment()->getAddress() + Data.getOffset();
+      }
+    }
+    Write32(Address);
   }
 
   void BindIndirectSymbols(MCAssembler &Asm,
@@ -640,17 +650,23 @@ public:
 MCFragment::MCFragment() : Kind(FragmentType(~0)) {
 }
 
-MCFragment::MCFragment(FragmentType _Kind, MCSectionData *SD)
+MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
   : Kind(_Kind),
+    Parent(_Parent),
     FileSize(~UINT64_C(0))
 {
-  if (SD)
-    SD->getFragmentList().push_back(this);
+  if (Parent)
+    Parent->getFragmentList().push_back(this);
 }
 
 MCFragment::~MCFragment() {
 }
 
+uint64_t MCFragment::getAddress() const {
+  assert(getParent() && "Missing Section!");
+  return getParent()->getAddress() + Offset;
+}
+
 /* *** */
 
 MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
@@ -658,6 +674,7 @@ MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
 MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
   : Section(_Section),
     Alignment(1),
+    Address(~UINT64_C(0)),
     FileSize(~UINT64_C(0))
 {
   if (A)
@@ -824,8 +841,12 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
 
 void MCAssembler::Finish() {
   // Layout the sections and fragments.
-  for (iterator it = begin(), ie = end(); it != ie; ++it)
+  uint64_t Address = 0;
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
+    it->setAddress(Address);
     LayoutSection(*it);
+    Address += it->getFileSize();
+  }
 
   // Write the object file.
   MachObjectWriter MOW(OS);
index de1c6ed712246a59fcced0585c0e9c43a2082202..bed0d43d3797fed36edc16cef986291fdc71ba49 100644 (file)
@@ -134,6 +134,7 @@ void MCMachOStreamer::SwitchSection(const MCSection *Section) {
 void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
 
+  // FIXME: We should also use offsets into Fill fragments.
   MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
   if (!F)
     F = new MCDataFragment(CurSectionData);
index 4592ead859a49000b152a44eb7f003fd0faa6709..1812ac3e1017017e4188dfcbb157cffef362f525 100644 (file)
@@ -117,8 +117,7 @@ sym_nlp_G:
 // CHECK:     # Section 2
 // CHECK:    (('section_name', '__nl_symbol_ptr\x00')
 // CHECK:     ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-        // FIXME: Enable this when fixed!
-// CHECX:     ('address', 20)
+// CHECK:     ('address', 20)
 // CHECK:     ('size', 20)
 // CHECK:     ('offset', 412)
 // CHECK:     ('alignment', 2)
@@ -145,8 +144,7 @@ sym_nlp_G:
 // CHECK:     ('n_type', 0xe)
 // CHECK:     ('n_sect', 2)
 // CHECK:     ('n_desc', 0)
-        // FIXME: Enable this when fixed!
-// CHECX:     ('n_value', 8)
+// CHECK:     ('n_value', 8)
 // CHECK:     ('_string', 'sym_lsp_C')
 // CHECK:    ),
 // CHECK:     # Symbol 1
@@ -154,8 +152,7 @@ sym_nlp_G:
 // CHECK:     ('n_type', 0xe)
 // CHECK:     ('n_sect', 3)
 // CHECK:     ('n_desc', 0)
-        // FIXME: Enable this when fixed!
-// CHECX:     ('n_value', 28)
+// CHECK:     ('n_value', 28)
 // CHECK:     ('_string', 'sym_nlp_C')
 // CHECK:    ),
 // CHECK:     # Symbol 2
@@ -163,8 +160,7 @@ sym_nlp_G:
 // CHECK:     ('n_type', 0xf)
 // CHECK:     ('n_sect', 2)
 // CHECK:     ('n_desc', 0)
-        // FIXME: Enable this when fixed!
-// CHECX:     ('n_value', 16)
+// CHECK:     ('n_value', 16)
 // CHECK:     ('_string', 'sym_lsp_G')
 // CHECK:    ),
 // CHECK:     # Symbol 3
@@ -172,8 +168,7 @@ sym_nlp_G:
 // CHECK:     ('n_type', 0xf)
 // CHECK:     ('n_sect', 3)
 // CHECK:     ('n_desc', 0)
-        // FIXME: Enable this when fixed!
-// CHECX:     ('n_value', 36)
+// CHECK:     ('n_value', 36)
 // CHECK:     ('_string', 'sym_nlp_G')
 // CHECK:    ),
 // CHECK:     # Symbol 4
diff --git a/test/MC/MachO/values.s b/test/MC/MachO/values.s
new file mode 100644 (file)
index 0000000..2a472ab
--- /dev/null
@@ -0,0 +1,135 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+        .long 0
+text_def_int:
+        .long 0
+
+        .globl text_def_ext
+text_def_ext:
+        .long 0
+
+        .data
+        .long 0
+data_def_int:
+        .long 0
+
+        .globl data_def_ext
+data_def_ext:
+        .long 0
+
+// CHECK: ('cputype', 7)
+// CHECK: ('cpusubtype', 3)
+// CHECK: ('filetype', 1)
+// CHECK: ('num_load_commands', 1)
+// CHECK: ('load_commands_size', 296)
+// CHECK: ('flag', 0)
+// CHECK: ('load_commands', [
+// CHECK:   # Load Command 0
+// CHECK:  (('command', 1)
+// CHECK:   ('size', 192)
+// 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', 24)
+// CHECK:   ('file_offset', 324)
+// CHECK:   ('file_size', 24)
+// CHECK:   ('maxprot', 7)
+// CHECK:   ('initprot', 7)
+// CHECK:   ('num_sections', 2)
+// 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', 12)
+// CHECK:     ('offset', 324)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 0)
+// CHECK:     ('num_reloc', 0)
+// CHECK:     ('flags', 0x80000000)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// 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', 12)
+// CHECK:     ('size', 12)
+// CHECK:     ('offset', 336)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 0)
+// CHECK:     ('num_reloc', 0)
+// CHECK:     ('flags', 0x0)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 1
+// CHECK:  (('command', 2)
+// CHECK:   ('size', 24)
+// CHECK:   ('symoff', 348)
+// CHECK:   ('nsyms', 4)
+// CHECK:   ('stroff', 396)
+// CHECK:   ('strsize', 56)
+// CHECK:   ('_string_data', '\x00text_def_ext\x00data_def_ext\x00text_def_int\x00data_def_int\x00\x00\x00\x00')
+// CHECK:   ('_symbols', [
+// CHECK:     # Symbol 0
+// CHECK:    (('n_strx', 27)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 1)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 4)
+// CHECK:     ('_string', 'text_def_int')
+// CHECK:    ),
+// CHECK:     # Symbol 1
+// CHECK:    (('n_strx', 40)
+// CHECK:     ('n_type', 0xe)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 16)
+// CHECK:     ('_string', 'data_def_int')
+// CHECK:    ),
+// CHECK:     # Symbol 2
+// CHECK:    (('n_strx', 14)
+// CHECK:     ('n_type', 0xf)
+// CHECK:     ('n_sect', 2)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 20)
+// CHECK:     ('_string', 'data_def_ext')
+// CHECK:    ),
+// CHECK:     # Symbol 3
+// CHECK:    (('n_strx', 1)
+// CHECK:     ('n_type', 0xf)
+// CHECK:     ('n_sect', 1)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 8)
+// CHECK:     ('_string', 'text_def_ext')
+// CHECK:    ),
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 2
+// CHECK:  (('command', 11)
+// CHECK:   ('size', 80)
+// CHECK:   ('ilocalsym', 0)
+// CHECK:   ('nlocalsym', 2)
+// CHECK:   ('iextdefsym', 2)
+// CHECK:   ('nextdefsym', 2)
+// CHECK:   ('iundefsym', 4)
+// CHECK:   ('nundefsym', 0)
+// 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: ])