From 7070387f08f7dc797b554ed8013cba9f8b74121a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 30 Sep 2010 02:22:20 +0000 Subject: [PATCH] Make it possible for the MCObjectWriter to decide if a given fixup is fully resolved or not. Different object files have different restrictions and different native assemblers have different idiosyncrasies we want to emulate for now. Move the existing MachO logic to the new place and implement an ELF one that gets fixups to globals right. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115131 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/ELFObjectWriter.h | 5 + include/llvm/MC/MCAssembler.h | 13 ++- include/llvm/MC/MCObjectWriter.h | 10 ++ include/llvm/MC/MachObjectWriter.h | 5 + lib/MC/ELFObjectWriter.cpp | 55 +++++++++- lib/MC/MCAssembler.cpp | 155 +++++------------------------ lib/MC/MachObjectWriter.cpp | 118 ++++++++++++++++++++++ lib/MC/WinCOFFObjectWriter.cpp | 12 +++ test/MC/ELF/relax.s | 38 +++++++ 9 files changed, 274 insertions(+), 137 deletions(-) create mode 100644 test/MC/ELF/relax.s diff --git a/include/llvm/MC/ELFObjectWriter.h b/include/llvm/MC/ELFObjectWriter.h index e5071066200..c8a42fe57b5 100644 --- a/include/llvm/MC/ELFObjectWriter.h +++ b/include/llvm/MC/ELFObjectWriter.h @@ -39,6 +39,11 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 524f2abae28..8d899d30d21 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -621,17 +621,19 @@ private: /// \return Whether the fixup value was fully resolved. This is true if the /// \arg Value result is fixed, otherwise the value may change due to /// relocation. - bool EvaluateFixup(const MCAsmLayout &Layout, + bool EvaluateFixup(const MCObjectWriter &Writer, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, + bool FixupNeedsRelaxation(const MCObjectWriter &Writer, + const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. - bool FragmentNeedsRelaxation(const MCInstFragment *IF, + bool FragmentNeedsRelaxation(const MCObjectWriter &Writer, + const MCInstFragment *IF, const MCAsmLayout &Layout) const; /// Compute the effective fragment size assuming it is layed out at the given @@ -642,7 +644,7 @@ private: /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. - bool LayoutOnce(MCAsmLayout &Layout); + bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout); /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); @@ -664,7 +666,8 @@ public: void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout, MCObjectWriter *OW) const; - void AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout); + void AddSectionToTheEnd(const MCObjectWriter &Writer, MCSectionData &SD, + MCAsmLayout &Layout); public: /// Construct a new assembler instance. diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index f1c1cb8a599..7de37f762d3 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -75,6 +75,16 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; + /// Check if a fixup is fully resolved. + /// + /// This routine is used by the assembler to let the file format decide + /// if a fixup is not fully resolved. For example, one that crosses + /// two sections on ELF. + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const = 0; + /// Write the object file. /// /// This routine is called by the assembler after layout and relaxation is diff --git a/include/llvm/MC/MachObjectWriter.h b/include/llvm/MC/MachObjectWriter.h index 9b1ff1db847..198da8fc173 100644 --- a/include/llvm/MC/MachObjectWriter.h +++ b/include/llvm/MC/MachObjectWriter.h @@ -36,6 +36,11 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index b60271f1b20..94251d76b28 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -274,6 +274,11 @@ namespace { void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, const MCSectionData *SD); + bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; @@ -775,7 +780,7 @@ void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, WriteRelocationsFragment(Asm, F, &SD); - Asm.AddSectionToTheEnd(RelaSD, Layout); + Asm.AddSectionToTheEnd(*Writer, RelaSD, Layout); } } @@ -873,11 +878,11 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm, // Symbol table F = new MCDataFragment(&SymtabSD); WriteSymbolTable(F, Asm, Layout, NumRegularSections); - Asm.AddSectionToTheEnd(SymtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout); F = new MCDataFragment(&StrtabSD); F->getContents().append(StringTable.begin(), StringTable.end()); - Asm.AddSectionToTheEnd(StrtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, StrtabSD, Layout); F = new MCDataFragment(&ShstrtabSD); @@ -903,7 +908,41 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm, F->getContents() += '\x00'; } - Asm.AddSectionToTheEnd(ShstrtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, ShstrtabSD, Layout); +} + +bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + // If this is a PCrel relocation, find the section this fixup value is + // relative to. + const MCSection *BaseSection = 0; + if (IsPCRel) { + BaseSection = &DF->getParent()->getSection(); + assert(BaseSection); + } + + const MCSection *SectionA = 0; + const MCSymbol *SymbolA = 0; + if (const MCSymbolRefExpr *A = Target.getSymA()) { + SymbolA = &A->getSymbol(); + SectionA = &SymbolA->getSection(); + } + + const MCSection *SectionB = 0; + if (const MCSymbolRefExpr *B = Target.getSymB()) { + SectionB = &B->getSymbol().getSection(); + } + + if (!BaseSection) + return SectionA == SectionB; + + const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA); + if (DataA.isExternal()) + return false; + + return !SectionB && BaseSection == SectionA; } void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm, @@ -1064,6 +1103,14 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, Target, FixedValue); } +bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, + IsPCRel, DF); +} + void ELFObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 506f2a650a1..3d9dcba52d6 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -232,89 +232,6 @@ MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, MCAssembler::~MCAssembler() { } -static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm, - const MCFixup &Fixup, - const MCValue Target, - const MCSection *BaseSection) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr() + - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr()) == 0. - // - // The simple (Darwin, except on x86_64) way of dealing with this was to - // assume that any reference to a temporary symbol *must* be a temporary - // symbol in the same atom, unless the sections differ. Therefore, any PCrel - // relocation to a temporary symbol (in the same section) is fully - // resolved. This also works in conjunction with absolutized .set, which - // requires the compiler to use .set to absolutize the differences between - // symbols which the compiler knows to be assembly time constants, so we don't - // need to worry about considering symbol differences fully resolved. - - // Non-relative fixups are only resolved if constant. - if (!BaseSection) - return Target.isAbsolute(); - - // Otherwise, relative fixups are only resolved if not a difference and the - // target is a temporary in the same section. - if (Target.isAbsolute() || Target.getSymB()) - return false; - - const MCSymbol *A = &Target.getSymA()->getSymbol(); - if (!A->isTemporary() || !A->isInSection() || - &A->getSection() != BaseSection) - return false; - - return true; -} - -static bool isScatteredFixupFullyResolved(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFixup &Fixup, - const MCValue Target, - const MCSymbolData *BaseSymbol) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr(BaseSymbol) + - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0. - // - // Note that "false" is almost always conservatively correct (it means we emit - // a relocation which is unnecessary), except when it would force us to emit a - // relocation which the target cannot encode. - - const MCSymbolData *A_Base = 0, *B_Base = 0; - if (const MCSymbolRefExpr *A = Target.getSymA()) { - // Modified symbol references cannot be resolved. - if (A->getKind() != MCSymbolRefExpr::VK_None) - return false; - - A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); - if (!A_Base) - return false; - } - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - // Modified symbol references cannot be resolved. - if (B->getKind() != MCSymbolRefExpr::VK_None) - return false; - - B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); - if (!B_Base) - return false; - } - - // If there is no base, A and B have to be the same atom for this fixup to be - // fully resolved. - if (!BaseSymbol) - return A_Base == B_Base; - - // Otherwise, B must be missing and A must be the base. - return !B_Base && BaseSymbol == A_Base; -} - bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { // Non-temporary labels should always be visible to the linker. if (!Symbol.isTemporary()) @@ -347,7 +264,8 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { return SD->getFragment()->getAtom(); } -bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, +bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, + const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::EvaluateFixup; @@ -377,31 +295,8 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, IsResolved = false; } - // If we are using scattered symbols, determine whether this value is actually - // resolved; scattering may cause atoms to move. - if (IsResolved && getBackend().hasScatteredSymbols()) { - if (getBackend().hasReliableSymbolDifference()) { - // If this is a PCrel relocation, find the base atom (identified by its - // symbol) that the fixup value is relative to. - const MCSymbolData *BaseSymbol = 0; - if (IsPCRel) { - BaseSymbol = DF->getAtom(); - if (!BaseSymbol) - IsResolved = false; - } - - if (IsResolved) - IsResolved = isScatteredFixupFullyResolved(*this, Layout, Fixup, Target, - BaseSymbol); - } else { - const MCSection *BaseSection = 0; - if (IsPCRel) - BaseSection = &DF->getParent()->getSection(); - - IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, Target, - BaseSection); - } - } + if (IsResolved) + IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF); if (IsPCRel) Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset(); @@ -668,7 +563,8 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD, assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD)); } -void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) { +void MCAssembler::AddSectionToTheEnd(const MCObjectWriter &Writer, + MCSectionData &SD, MCAsmLayout &Layout) { // Create dummy fragments and assign section ordinals. unsigned SectionIndex = 0; for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) @@ -697,7 +593,7 @@ void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) { Layout.LayoutSection(&SD); // Layout until everything fits. - while (LayoutOnce(Layout)) + while (LayoutOnce(Writer, Layout)) continue; } @@ -756,8 +652,17 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { it2->setLayoutOrder(FragmentIndex++); } + llvm::OwningPtr OwnWriter(0); + if (Writer == 0) { + //no custom Writer_ : create the default one life-managed by OwningPtr + OwnWriter.reset(getBackend().createObjectWriter(OS)); + Writer = OwnWriter.get(); + if (!Writer) + report_fatal_error("unable to create object writer!"); + } + // Layout until everything fits. - while (LayoutOnce(Layout)) + while (LayoutOnce(*Writer, Layout)) continue; DEBUG_WITH_TYPE("mc-dump", { @@ -773,15 +678,6 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { uint64_t StartOffset = OS.tell(); - llvm::OwningPtr OwnWriter(0); - if (Writer == 0) { - //no custom Writer_ : create the default one life-managed by OwningPtr - OwnWriter.reset(getBackend().createObjectWriter(OS)); - Writer = OwnWriter.get(); - if (!Writer) - report_fatal_error("unable to create object 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); @@ -801,7 +697,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; - if (!EvaluateFixup(Layout, Fixup, DF, Target, FixedValue)) { + if (!EvaluateFixup(*Writer, Layout, Fixup, DF, Target, FixedValue)) { // The fixup was unresolved, we need a relocation. Inform the object // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. @@ -819,7 +715,8 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { stats::ObjectBytes += OS.tell() - StartOffset; } -bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, +bool MCAssembler::FixupNeedsRelaxation(const MCObjectWriter &Writer, + const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const { if (getRelaxAll()) @@ -828,7 +725,7 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, // If we cannot resolve the fixup value, it requires relaxation. MCValue Target; uint64_t Value; - if (!EvaluateFixup(Layout, Fixup, DF, Target, Value)) + if (!EvaluateFixup(Writer, Layout, Fixup, DF, Target, Value)) return true; // Otherwise, relax if the value is too big for a (signed) i8. @@ -837,7 +734,8 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, return int64_t(Value) != int64_t(int8_t(Value)); } -bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, +bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer, + const MCInstFragment *IF, const MCAsmLayout &Layout) const { // If this inst doesn't ever need relaxation, ignore it. This occurs when we // are intentionally pushing out inst fragments, or because we relaxed a @@ -847,13 +745,14 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(), ie = IF->fixup_end(); it != ie; ++it) - if (FixupNeedsRelaxation(*it, IF, Layout)) + if (FixupNeedsRelaxation(Writer, *it, IF, Layout)) return true; return false; } -bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { +bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, + MCAsmLayout &Layout) { ++stats::RelaxationSteps; // Layout the sections in order. @@ -868,7 +767,7 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { ie2 = SD.end(); it2 != ie2; ++it2) { // Check if this is an instruction fragment that needs relaxation. MCInstFragment *IF = dyn_cast(it2); - if (!IF || !FragmentNeedsRelaxation(IF, Layout)) + if (!IF || !FragmentNeedsRelaxation(Writer, IF, Layout)) continue; ++stats::RelaxedInstructions; diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index f81862e9ab1..02a5575606d 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -75,6 +75,86 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { return false; } +static bool isScatteredFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + const MCSymbolData *BaseSymbol) { + // The effective fixup address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // - addr(BaseSymbol) + + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0. + // + // Note that "false" is almost always conservatively correct (it means we emit + // a relocation which is unnecessary), except when it would force us to emit a + // relocation which the target cannot encode. + + const MCSymbolData *A_Base = 0, *B_Base = 0; + if (const MCSymbolRefExpr *A = Target.getSymA()) { + // Modified symbol references cannot be resolved. + if (A->getKind() != MCSymbolRefExpr::VK_None) + return false; + + A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); + if (!A_Base) + return false; + } + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + // Modified symbol references cannot be resolved. + if (B->getKind() != MCSymbolRefExpr::VK_None) + return false; + + B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); + if (!B_Base) + return false; + } + + // If there is no base, A and B have to be the same atom for this fixup to be + // fully resolved. + if (!BaseSymbol) + return A_Base == B_Base; + + // Otherwise, B must be missing and A must be the base. + return !B_Base && BaseSymbol == A_Base; +} + +static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm, + const MCValue Target, + const MCSection *BaseSection) { + // The effective fixup address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // - addr() + + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) - addr()) == 0. + // + // The simple (Darwin, except on x86_64) way of dealing with this was to + // assume that any reference to a temporary symbol *must* be a temporary + // symbol in the same atom, unless the sections differ. Therefore, any PCrel + // relocation to a temporary symbol (in the same section) is fully + // resolved. This also works in conjunction with absolutized .set, which + // requires the compiler to use .set to absolutize the differences between + // symbols which the compiler knows to be assembly time constants, so we don't + // need to worry about considering symbol differences fully resolved. + + // Non-relative fixups are only resolved if constant. + if (!BaseSection) + return Target.isAbsolute(); + + // Otherwise, relative fixups are only resolved if not a difference and the + // target is a temporary in the same section. + if (Target.isAbsolute() || Target.getSymB()) + return false; + + const MCSymbol *A = &Target.getSymA()->getSymbol(); + if (!A->isTemporary() || !A->isInSection() || + &A->getSection() != BaseSection) + return false; + + return true; +} + namespace { class MachObjectWriterImpl { @@ -1038,6 +1118,36 @@ public: UndefinedSymbolData); } + + bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + // If we are using scattered symbols, determine whether this value is + // actually resolved; scattering may cause atoms to move. + if (Asm.getBackend().hasScatteredSymbols()) { + if (Asm.getBackend().hasReliableSymbolDifference()) { + // If this is a PCrel relocation, find the base atom (identified by its + // symbol) that the fixup value is relative to. + const MCSymbolData *BaseSymbol = 0; + if (IsPCRel) { + BaseSymbol = DF->getAtom(); + if (!BaseSymbol) + return false; + } + + return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol); + } else { + const MCSection *BaseSection = 0; + if (IsPCRel) + BaseSection = &DF->getParent()->getSection(); + + return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection); + } + } + return true; + } + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); @@ -1224,6 +1334,14 @@ void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, Target, FixedValue); } +bool MachObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return ((MachObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, + IsPCRel, DF); +} + void MachObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { ((MachObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 6bebe46f96b..1cc5c09a083 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -181,6 +181,11 @@ public: MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; } @@ -690,6 +695,13 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, coff_section->Relocations.push_back(Reloc); } +bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return false; +} + void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { // Assign symbol and section indexes and offsets. diff --git a/test/MC/ELF/relax.s b/test/MC/ELF/relax.s new file mode 100644 index 00000000000..5c5e7e30dac --- /dev/null +++ b/test/MC/ELF/relax.s @@ -0,0 +1,38 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +// Test that we do a relaxation for foo but not for bar. Relaxing foo is +// probably not necessary, but matches what gnu as does. + +// Also test that the relaxation done for foo uses the symbol, not section and +// offset. + +bar: +.globl foo +foo: + jmp bar + jmp foo + +// CHECK: ('sh_name', 1) # '.text' +// CHECK-NEXT: ('sh_type', 1) +// CHECK-NEXT: ('sh_flags', 6) +// CHECK-NEXT: ('sh_addr', 0) +// CHECK-NEXT: ('sh_offset', 64) +// CHECK-NEXT: ('sh_size', 7) +// CHECK-NEXT: ('sh_link', 0) +// CHECK-NEXT: ('sh_info', 0) +// CHECK-NEXT: ('sh_addralign', 4) +// CHECK-NEXT: ('sh_entsize', 0) +// CHECK-NEXT: ('_section_data', 'ebfee900 000000') + +// CHECK: # Symbol 5 +// CHECK-NEXT: (('st_name', 5) # 'foo' + +// CHECK: .rela.text +// CHECK: ('_relocations', [ +// CHECK-NEXT: Relocation 0 +// CHECK-NEXT: (('r_offset', 3) +// CHECK-NEXT: ('r_sym', 5) +// CHECK-NEXT: ('r_type', 2) +// CHECK-NEXT: ('r_addend', -4) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) -- 2.34.1