From 85f2ecc697a8ca6c8cf08093054cbbb9d2060ccf Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 7 Dec 2010 00:27:36 +0000 Subject: [PATCH] Sorry for such a large commit. The summary is that only MachO cares about the actuall addresses in a .o file, so it is better to let the MachO writer compute it. This is good for two reasons. First, areas that shouldn't care about addresses now don't have access to it. Second, the layout of each section is independent. I should use this in a subsequent commit to speed it up. Most of the patch is just removing the section address computation. The two interesting parts are the change on how we handle padding in the end of sections and how MachO can get the address of a-b when a and b are in different sections. Since now the expression evaluation normally doesn't know the section address, it will think that a-b needs relocation and let the MachO writer know. Once it has computed the section addresses, it calls back the expression evaluation with the section addresses to resolve these expressions. The remaining problem is the handling of padding. Currently it will create a special alignment fragment at the end. Since that fragment doesn't update the alignment of the section, it needs the real address to be computed. Since now the layout will not compute a-b with a and b in different sections, the only effect that the special alignment fragment has is update the address size of the section. This can also be done by the MachO writer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121076 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAsmLayout.h | 23 ------ include/llvm/MC/MCAssembler.h | 21 +---- include/llvm/MC/MCExpr.h | 9 ++- include/llvm/MC/MCObjectStreamer.h | 3 +- include/llvm/MC/MCObjectWriter.h | 3 +- lib/MC/ELFObjectWriter.cpp | 14 ++-- lib/MC/MCAssembler.cpp | 122 ++++------------------------- lib/MC/MCELFStreamer.cpp | 2 +- lib/MC/MCExpr.cpp | 59 +++++++++----- lib/MC/MCMachOStreamer.cpp | 2 +- lib/MC/MCObjectStreamer.cpp | 4 +- lib/MC/MCPureStreamer.cpp | 3 +- lib/MC/MachObjectWriter.cpp | 101 ++++++++++++++++++++---- lib/MC/WinCOFFObjectWriter.cpp | 7 +- lib/MC/WinCOFFStreamer.cpp | 2 +- 15 files changed, 169 insertions(+), 206 deletions(-) diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index ce9692dcaff..805af6257f9 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -66,11 +66,6 @@ public: /// been initialized. void LayoutFragment(MCFragment *Fragment); - /// \brief Performs initial layout for a single section, assuming that the - /// previous section (including its fragments) has already been layed out - /// correctly. - void LayoutSection(MCSectionData *SD); - /// @name Section Access (in layout order) /// @{ @@ -92,21 +87,10 @@ public: /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; - /// @} - /// @name Section Layout Data - /// @{ - - /// \brief Get the computed address of the given section. - uint64_t getSectionAddress(const MCSectionData *SD) const; - /// @} /// @name Utility Functions /// @{ - /// \brief Get the address of the given fragment, as computed in the current - /// layout. - uint64_t getFragmentAddress(const MCFragment *F) const; - /// \brief Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. @@ -116,13 +100,6 @@ public: /// file. This may include additional padding, or be 0 for virtual sections. uint64_t getSectionFileSize(const MCSectionData *SD) const; - /// \brief Get the logical data size of the given section. - uint64_t getSectionSize(const MCSectionData *SD) const; - - /// \brief Get the address of the given symbol, as computed in the current - /// layout. - uint64_t getSymbolAddress(const MCSymbolData *SD) const; - /// \brief Get the offset of the given symbol, as computed in the current /// layout. uint64_t getSymbolOffset(const MCSymbolData *SD) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index ba894369819..8a5009ffc42 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -236,19 +236,12 @@ class MCAlignFragment : public MCFragment { /// target dependent. bool EmitNops : 1; - /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust - /// the address space size of a section and that it should not be included as - /// part of the section size. This flag can only be used on the last fragment - /// in a section. - bool OnlyAlignAddress : 1; - public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false), - OnlyAlignAddress(false) {} + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} /// @name Accessors /// @{ @@ -264,9 +257,6 @@ public: bool hasEmitNops() const { return EmitNops; } void setEmitNops(bool Value) { EmitNops = Value; } - bool hasOnlyAlignAddress() const { return OnlyAlignAddress; } - void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; } - /// @} static bool classof(const MCFragment *F) { @@ -447,10 +437,6 @@ 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; - /// HasInstructions - Whether this section has had instructions emitted into /// it. unsigned HasInstructions : 1; @@ -679,7 +665,6 @@ private: unsigned RelaxAll : 1; unsigned SubsectionsViaSymbols : 1; - unsigned PadSectionToAlignment : 1; private: /// Evaluate a fixup to a relocatable expression and the value which should be @@ -713,7 +698,6 @@ private: /// Compute the effective fragment size assuming it is layed out at the given /// \arg SectionAddress and \arg FragmentOffset. uint64_t ComputeFragmentSize(const MCFragment &F, - uint64_t SectionAddress, uint64_t FragmentOffset) const; /// LayoutOnce - Perform one layout iteration and return true if any offsets @@ -765,8 +749,7 @@ public: // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, - MCCodeEmitter &_Emitter, bool _PadSectionToAlignment, - raw_ostream &OS); + MCCodeEmitter &_Emitter, raw_ostream &OS); ~MCAssembler(); MCContext &getContext() const { return Context; } diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 888934e822f..da3cebe414e 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCEXPR_H #define LLVM_MC_MCEXPR_H +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" @@ -18,10 +19,12 @@ class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; +class MCSectionData; class MCSymbol; class MCValue; class raw_ostream; class StringRef; +typedef DenseMap SectionAddrMap; /// MCExpr - Base class for the full range of assembler expressions which are /// needed for parsing. @@ -42,12 +45,14 @@ private: void operator=(const MCExpr&); // DO NOT IMPLEMENT bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout) const; + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const; protected: explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; public: /// @name Accessors @@ -76,6 +81,8 @@ public: bool EvaluateAsAbsolute(int64_t &Res) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const; /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable /// value, i.e. an expression of the fixed form (a - b + constant). diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index d130ba4bcda..c6dd96068ff 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -37,8 +37,7 @@ class MCObjectStreamer : public MCStreamer { protected: MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool _PadSectionToAlignment); + raw_ostream &_OS, MCCodeEmitter *_Emitter); ~MCObjectStreamer(); MCSectionData *getCurrentSectionData() const { diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 90fe6e8ee15..b819a5778f3 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -62,7 +62,8 @@ public: /// /// This routine is called by the assembler after layout and relaxation is /// complete. - virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0; + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; /// Record a relocation entry. /// diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4daab49089a..b51e508ab26 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -325,7 +325,8 @@ namespace { virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap); - virtual void ExecutePostLayoutBinding(MCAssembler &Asm); + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout); virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, uint64_t Address, uint64_t Offset, @@ -557,7 +558,8 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { return 0; } -void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { +void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. @@ -1365,11 +1367,11 @@ static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, return Layout.getSectionFileSize(&SD); } -static uint64_t GetSectionSize(const MCAsmLayout &Layout, - const MCSectionData &SD) { +static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { if (IsELFMetaDataSection(SD)) return DataSectionSize(SD); - return Layout.getSectionSize(&SD); + return Layout.getSectionAddressSize(&SD); } static void WriteDataSectionData(ELFObjectWriter *W, const MCSectionData &SD) { @@ -1479,7 +1481,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, else GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]); - uint64_t Size = GetSectionSize(Layout, SD); + uint64_t Size = GetSectionAddressSize(Layout, SD); WriteSection(Asm, SectionIndexMap, GroupSymbolIndex, SectionOffsetMap[&Section], Size, diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 299eb0ab67c..4f63a081ae8 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -38,7 +38,6 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts"); STATISTIC(ObjectBytes, "Number of emitted object file bytes"); STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); -STATISTIC(SectionLayouts, "Number of section layouts"); } } @@ -113,11 +112,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const { } } -uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const { - assert(F->getParent() && "Missing section()!"); - return getSectionAddress(F->getParent()) + getFragmentOffset(F); -} - uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const { EnsureValid(F); assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!"); @@ -135,17 +129,6 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { return getFragmentOffset(SD->getFragment()) + SD->getOffset(); } -uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const { - assert(SD->getFragment() && "Invalid getAddress() on undefined symbol!"); - return getFragmentAddress(SD->getFragment()) + SD->getOffset(); -} - -uint64_t MCAsmLayout::getSectionAddress(const MCSectionData *SD) const { - EnsureValid(SD->begin()); - assert(SD->Address != ~UINT64_C(0) && "Address not set!"); - return SD->Address; -} - uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { // The size is the last fragment's end offset. const MCFragment &F = SD->getFragmentList().back(); @@ -161,17 +144,6 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { return getSectionAddressSize(SD); } -uint64_t MCAsmLayout::getSectionSize(const MCSectionData *SD) const { - // The logical size is the address space size minus any tail padding. - uint64_t Size = getSectionAddressSize(SD); - const MCAlignFragment *AF = - dyn_cast(&(SD->getFragmentList().back())); - if (AF && AF->hasOnlyAlignAddress()) - Size -= getFragmentEffectiveSize(AF); - - return Size; -} - /* *** */ MCFragment::MCFragment() : Kind(FragmentType(~0)) { @@ -196,7 +168,6 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(&_Section), Ordinal(~UINT32_C(0)), Alignment(1), - Address(~UINT64_C(0)), HasInstructions(false) { if (A) @@ -221,11 +192,9 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, /* *** */ MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, - MCCodeEmitter &_Emitter, bool _PadSectionToAlignment, - raw_ostream &_OS) + MCCodeEmitter &_Emitter, raw_ostream &_OS) : Context(_Context), Backend(_Backend), Emitter(_Emitter), - OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false), - PadSectionToAlignment(_PadSectionToAlignment) + OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false) { } @@ -285,14 +254,14 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, if (const MCSymbolRefExpr *A = Target.getSymA()) { const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); if (Sym.isDefined()) - Value += Layout.getSymbolAddress(&getSymbolData(Sym)); + Value += Layout.getSymbolOffset(&getSymbolData(Sym)); else IsResolved = false; } if (const MCSymbolRefExpr *B = Target.getSymB()) { const MCSymbol &Sym = B->getSymbol().AliasedSymbol(); if (Sym.isDefined()) - Value -= Layout.getSymbolAddress(&getSymbolData(Sym)); + Value -= Layout.getSymbolOffset(&getSymbolData(Sym)); else IsResolved = false; } @@ -301,13 +270,12 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF); if (IsPCRel) - Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset(); + Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset(); return IsResolved; } uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F, - uint64_t SectionAddress, uint64_t FragmentOffset) const { switch (F.getKind()) { case MCFragment::FT_Data: @@ -323,11 +291,7 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F, case MCFragment::FT_Align: { const MCAlignFragment &AF = cast(F); - assert((!AF.hasOnlyAlignAddress() || !AF.getNextNode()) && - "Invalid OnlyAlignAddress bit, not the last fragment!"); - - uint64_t Size = OffsetToAlignment(SectionAddress + FragmentOffset, - AF.getAlignment()); + uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment()); // Honor MaxBytesToEmit. if (Size > AF.getMaxBytesToEmit()) @@ -351,8 +315,6 @@ void MCAsmLayout::LayoutFile() { // Initialize the first section and set the valid fragment layout point. All // actual layout computations are done lazily. LastValidFragment = 0; - if (!getSectionOrder().empty()) - getSectionOrder().front()->Address = 0; } void MCAsmLayout::LayoutFragment(MCFragment *F) { @@ -371,43 +333,14 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) { ++stats::FragmentLayouts; - // Compute the fragment start address. - uint64_t StartAddress = F->getParent()->Address; - uint64_t Address = StartAddress; + // Compute fragment offset and size. + uint64_t Offset = 0; if (Prev) - Address += Prev->Offset + Prev->EffectiveSize; + Offset += Prev->Offset + Prev->EffectiveSize; - // Compute fragment offset and size. - F->Offset = Address - StartAddress; - F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress, - F->Offset); + F->Offset = Offset; + F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset); LastValidFragment = F; - - // If this is the last fragment in a section, update the next section address. - if (!F->getNextNode()) { - unsigned NextIndex = F->getParent()->getLayoutOrder() + 1; - if (NextIndex != getSectionOrder().size()) - LayoutSection(getSectionOrder()[NextIndex]); - } -} - -void MCAsmLayout::LayoutSection(MCSectionData *SD) { - unsigned SectionOrderIndex = SD->getLayoutOrder(); - - ++stats::SectionLayouts; - - // Compute the section start address. - uint64_t StartAddress = 0; - if (SectionOrderIndex) { - MCSectionData *Prev = getSectionOrder()[SectionOrderIndex - 1]; - StartAddress = getSectionAddress(Prev) + getSectionAddressSize(Prev); - } - - // Honor the section alignment requirements. - StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment()); - - // Set the section address. - SD->Address = StartAddress; } /// WriteFragmentData - Write the \arg F data to the output file. @@ -566,7 +499,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD, ie = SD->end(); it != ie; ++it) WriteFragmentData(*this, Layout, *it, OW); - assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD)); + assert(OW->getStream().tell() - Start == Layout.getSectionAddressSize(SD)); } @@ -594,29 +527,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { // Create the layout object. MCAsmLayout Layout(*this); - // Insert additional align fragments for concrete sections to explicitly pad - // the previous section to match their alignment requirements. This is for - // 'gas' compatibility, it shouldn't strictly be necessary. - if (PadSectionToAlignment) { - for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) { - MCSectionData *SD = Layout.getSectionOrder()[i]; - - // Ignore sections without alignment requirements. - unsigned Align = SD->getAlignment(); - if (Align <= 1) - continue; - - // Ignore virtual sections, they don't cause file size modifications. - if (SD->getSection().isVirtualSection()) - continue; - - // Otherwise, create a new align fragment at the end of the previous - // section. - MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align, - Layout.getSectionOrder()[i - 1]); - AF->setOnlyAlignAddress(true); - } - } + // Create dummy fragments and assign section ordinals. unsigned SectionIndex = 0; @@ -668,7 +579,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { // Allow the object writer a chance to perform post-layout binding (for // example, to set the index fields in the symbol data). - Writer->ExecutePostLayoutBinding(*this); + Writer->ExecutePostLayoutBinding(*this, Layout); // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { @@ -920,8 +831,6 @@ void MCFragment::dump() { const MCAlignFragment *AF = cast(this); if (AF->hasEmitNops()) OS << " (emit nops)"; - if (AF->hasOnlyAlignAddress()) - OS << " (only align section)"; OS << "\n "; OS << " Alignment:" << AF->getAlignment() << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize() @@ -991,8 +900,7 @@ void MCSectionData::dump() { raw_ostream &OS = llvm::errs(); OS << "dump(); diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index f18c420cb9b..18d8fa39edd 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -71,7 +71,7 @@ class MCELFStreamer : public MCObjectStreamer { public: MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter, false) {} + : MCObjectStreamer(Context, TAB, OS, Emitter) {} ~MCELFStreamer() {} diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index b4712c20355..756e7598d5d 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -238,20 +238,27 @@ void MCTargetExpr::Anchor() {} /* *** */ bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { - return EvaluateAsAbsolute(Res, 0, 0); + return EvaluateAsAbsolute(Res, 0, 0, 0); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const { - return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout); + return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0); +} + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, + const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const { + return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { - return EvaluateAsAbsolute(Res, &Asm, 0); + return EvaluateAsAbsolute(Res, &Asm, 0, 0); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout) const { + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const { MCValue Value; // Fast path constants. @@ -260,7 +267,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, return true; } - if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, false) || + if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) || !Value.isAbsolute()) { // EvaluateAsAbsolute is defined to return the "current value" of // the expression if we are given a Layout object, even in cases @@ -268,11 +275,11 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, if (Layout) { Res = Value.getConstant(); if (Value.getSymA()) { - Res += Layout->getSymbolAddress( + Res += Layout->getSymbolOffset( &Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol())); } if (Value.getSymB()) { - Res -= Layout->getSymbolAddress( + Res -= Layout->getSymbolOffset( &Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol())); } } @@ -283,8 +290,9 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, return true; } -static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, - const MCAssembler *Asm, +static bool EvaluateSymbolicAdd(const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS,const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, @@ -327,10 +335,19 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, } if (Layout) { - Res = MCValue::get(+ Layout->getSymbolAddress(&AD) - - Layout->getSymbolAddress(&BD) - + LHS.getConstant() - + RHS_Cst); + const MCSectionData &SecA = *AD.getFragment()->getParent(); + const MCSectionData &SecB = *BD.getFragment()->getParent(); + int64_t Val = + Layout->getSymbolOffset(&AD) + - Layout->getSymbolOffset(&BD) + + LHS.getConstant() + + RHS_Cst; + if (&SecA != &SecB) { + if (!Addrs) + return false; + Val += Addrs->lookup(&SecA); + Val -= Addrs->lookup(&SecB); + } + Res = MCValue::get(Val); return true; } } @@ -344,14 +361,15 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const { if (Layout) return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout, - false); + 0, false); else - return EvaluateAsRelocatableImpl(Res, 0, 0, false); + return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false); } bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const { ++stats::MCExprEvaluate; @@ -371,6 +389,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, Layout, + Addrs, true); // If we failed to simplify this to a constant, let the target // handle it. @@ -387,7 +406,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, MCValue Value; if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, - InSet)) + Addrs, InSet)) return false; switch (AUE->getOpcode()) { @@ -421,9 +440,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, MCValue LHSValue, RHSValue; if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, - InSet) || + Addrs, InSet) || !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, - InSet)) + Addrs, InSet)) return false; // We only support a few operations on non-constant expressions, handle @@ -434,13 +453,13 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, return false; case MCBinaryExpr::Sub: // Negate RHS and add. - return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue, + return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, RHSValue.getSymB(), RHSValue.getSymA(), -RHSValue.getConstant(), Res); case MCBinaryExpr::Add: - return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue, + return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, RHSValue.getSymA(), RHSValue.getSymB(), RHSValue.getConstant(), Res); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 1ee2d482602..6f360010378 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -36,7 +36,7 @@ private: public: MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter, true) {} + : MCObjectStreamer(Context, TAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 6348a2b69ec..683f2c6adc6 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -19,11 +19,9 @@ using namespace llvm; MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool _PadSectionToAlignment) + raw_ostream &_OS, MCCodeEmitter *_Emitter) : MCStreamer(Context), Assembler(new MCAssembler(Context, TAB, *_Emitter, - _PadSectionToAlignment, _OS)), CurSectionData(0) { diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index af23c912117..5341844f740 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -30,8 +30,7 @@ private: public: MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter, - /*PadSectionToAlignment=*/true) {} + : MCObjectStreamer(Context, TAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 1236dc11267..de96d64c279 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -197,6 +197,34 @@ class MachObjectWriter : public MCObjectWriter { /// @} + SectionAddrMap SectionAddress; + uint64_t getSectionAddress(const MCSectionData* SD) const { + return SectionAddress.lookup(SD); + } + uint64_t getSymbolAddress(const MCSymbolData* SD, + const MCAsmLayout &Layout) const { + return getSectionAddress(SD->getFragment()->getParent()) + + Layout.getSymbolOffset(SD); + } + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const { + return getSectionAddress(Fragment->getParent()) + + Layout.getFragmentOffset(Fragment); + } + + uint64_t getPaddingSize(const MCSectionData *SD, + const MCAsmLayout &Layout) const { + uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD); + unsigned Next = SD->getLayoutOrder() + 1; + if (Next >= Layout.getSectionOrder().size()) + return 0; + + const MCSectionData &NextSD = *Layout.getSectionOrder()[Next]; + if (NextSD.getSection().isVirtualSection()) + return 0; + return OffsetToAlignment(EndAddr, NextSD.getAlignment()); + } + unsigned Is64Bit : 1; uint32_t CPUType; @@ -283,7 +311,7 @@ public: void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCSectionData &SD, uint64_t FileOffset, uint64_t RelocationsStart, unsigned NumRelocations) { - uint64_t SectionSize = Layout.getSectionSize(&SD); + uint64_t SectionSize = Layout.getSectionAddressSize(&SD); // The offset is unused for virtual sections. if (SD.getSection().isVirtualSection()) { @@ -301,10 +329,10 @@ public: WriteBytes(Section.getSectionName(), 16); WriteBytes(Section.getSegmentName(), 16); if (Is64Bit) { - Write64(Layout.getSectionAddress(&SD)); // address + Write64(getSectionAddress(&SD)); // address Write64(SectionSize); // size } else { - Write32(Layout.getSectionAddress(&SD)); // address + Write32(getSectionAddress(&SD)); // address Write32(SectionSize); // size } Write32(FileOffset); @@ -413,7 +441,7 @@ public: if (Symbol.isAbsolute()) { Address = cast(Symbol.getVariableValue())->getValue(); } else { - Address = Layout.getSymbolAddress(&Data); + Address = getSymbolAddress(&Data, Layout); } } else if (Data.isCommon()) { // Common symbols are encoded with the size in the address @@ -473,7 +501,7 @@ public: uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); uint32_t FixupAddress = - Layout.getFragmentAddress(Fragment) + Fixup.getOffset(); + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); int64_t Value = 0; unsigned Index = 0; unsigned IsExtern = 0; @@ -603,10 +631,21 @@ public: // The index is the section ordinal (1-based). Index = SD.getFragment()->getParent()->getOrdinal() + 1; IsExtern = 0; - Value += Layout.getSymbolAddress(&SD); + Value += getSymbolAddress(&SD, Layout); if (IsPCRel) Value -= FixupAddress + (1 << Log2Size); + } else if (Symbol->isVariable()) { + const MCExpr *Value = Symbol->getVariableValue(); + int64_t Res; + bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress); + if (isAbs) { + FixedValue = Res; + return; + } else { + report_fatal_error("unsupported relocation of variable '" + + Symbol->getName() + "'"); + } } else { report_fatal_error("unsupported relocation of undefined symbol '" + Symbol->getName() + "'"); @@ -708,7 +747,9 @@ public: report_fatal_error("symbol '" + A->getName() + "' can not be undefined in a subtraction expression"); - uint32_t Value = Layout.getSymbolAddress(A_SD); + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; uint32_t Value2 = 0; if (const MCSymbolRefExpr *B = Target.getSymB()) { @@ -725,7 +766,8 @@ public: // for pedantic compatibility with 'as'. Type = A_SD->isExternal() ? macho::RIT_Difference : macho::RIT_LocalDifference; - Value2 = Layout.getSymbolAddress(B_SD); + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); } // Relocations are written out in reverse order, so the PAIR comes first. @@ -774,10 +816,10 @@ public: if (Target.getSymB()) { // If this is a subtraction then we're pcrel. uint32_t FixupAddress = - Layout.getFragmentAddress(Fragment) + Fixup.getOffset(); + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); IsPCRel = 1; - FixedValue = (FixupAddress - Layout.getSymbolAddress(SD_B) + + FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) + Target.getConstant()); FixedValue += 1ULL << Log2Size; } else { @@ -855,10 +897,13 @@ public: // 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); + FixedValue -= getSymbolAddress(SD, Layout); } else { // The index is the section ordinal (1-based). Index = SD->getFragment()->getParent()->getOrdinal() + 1; + FixedValue += getSectionAddress(SD->getFragment()->getParent()); + if (IsPCRel) + FixedValue -= getSectionAddress(Fragment->getParent()); } Type = macho::RIT_Vanilla; @@ -1039,7 +1084,25 @@ public: StringTable += '\x00'; } - void ExecutePostLayoutBinding(MCAssembler &Asm) { + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout) { + uint64_t StartAddress = 0; + const SmallVectorImpl &Order = Layout.getSectionOrder(); + for (int i = 0, n = Order.size(); i != n ; ++i) { + const MCSectionData *SD = Order[i]; + StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment()); + SectionAddress[SD] = StartAddress; + StartAddress += Layout.getSectionAddressSize(SD); + // Explicitly pad the section to match the alignment requirements of the + // following one. This is for 'gas' compatibility, it shouldn't + /// strictly be necessary. + StartAddress += getPaddingSize(SD, Layout); + } + } + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { + computeSectionAddresses(Asm, Layout); + // Create symbol data for any indirect symbols. BindIndirectSymbols(Asm); @@ -1113,9 +1176,10 @@ public: for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData &SD = *it; - uint64_t Address = Layout.getSectionAddress(&SD); - uint64_t Size = Layout.getSectionSize(&SD); + uint64_t Address = getSectionAddress(&SD); + uint64_t Size = Layout.getSectionAddressSize(&SD); uint64_t FileSize = Layout.getSectionFileSize(&SD); + FileSize += getPaddingSize(&SD, Layout); VMSize = std::max(VMSize, Address + Size); @@ -1144,7 +1208,7 @@ public: ie = Asm.end(); it != ie; ++it) { std::vector &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); - uint64_t SectionStart = SectionDataStart + Layout.getSectionAddress(it); + uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); RelocTableEnd += NumRelocs * macho::RelocationInfoSize; } @@ -1185,9 +1249,14 @@ public: // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) + ie = Asm.end(); it != ie; ++it) { Asm.WriteSectionData(it, Layout, this); + uint64_t Pad = getPaddingSize(it, Layout); + for (unsigned int i = 0; i < Pad; ++i) + Write8(0); + } + // Write the extra padding. WriteZeros(SectionDataPadding); diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 1bfd3a4fd7a..66fd92015ff 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -170,7 +170,7 @@ public: // MCObjectWriter interface implementation. - void ExecutePostLayoutBinding(MCAssembler &Asm); + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -616,7 +616,8 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { //////////////////////////////////////////////////////////////////////////////// // MCObjectWriter interface implementations -void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { +void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. @@ -753,7 +754,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { - if (Layout.getSectionSize((*i)->MCData) > 0) { + if (Layout.getSectionAddressSize((*i)->MCData) > 0) { MakeSectionReal(**i, ++Header.NumberOfSections); } else { (*i)->Number = -1; diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 3654add4f40..46968e601be 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -124,7 +124,7 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, TargetAsmBackend &TAB, MCCodeEmitter &CE, raw_ostream &OS) - : MCObjectStreamer(Context, TAB, OS, &CE, false) + : MCObjectStreamer(Context, TAB, OS, &CE) , CurSymbol(NULL) { } -- 2.34.1