From 5e835967dd5dda294d0ef3392f4c1d4a2260f532 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 26 Aug 2009 02:48:04 +0000 Subject: [PATCH] llvm-mc/Mach-O: Set addresses for symbols. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80065 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAssembler.h | 20 ++++- lib/MC/MCAssembler.cpp | 41 +++++++--- lib/MC/MCMachOStreamer.cpp | 1 + test/MC/MachO/symbol-indirect.s | 15 ++-- test/MC/MachO/values.s | 135 ++++++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+), 21 deletions(-) create mode 100644 test/MC/MachO/values.s diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index b5ee5017cc9..ce9dca1ae12 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -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; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index fc5d31ca50b..13c193275cb 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -216,7 +216,7 @@ public: static_cast(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 . @@ -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); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index de1c6ed7122..bed0d43d379 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -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(getCurrentFragment()); if (!F) F = new MCDataFragment(CurSectionData); diff --git a/test/MC/MachO/symbol-indirect.s b/test/MC/MachO/symbol-indirect.s index 4592ead859a..1812ac3e101 100644 --- a/test/MC/MachO/symbol-indirect.s +++ b/test/MC/MachO/symbol-indirect.s @@ -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 index 00000000000..2a472ab6071 --- /dev/null +++ b/test/MC/MachO/values.s @@ -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: ]) -- 2.34.1