From 224dbf4aec6488e6ac55f2155a238e57086ef473 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 29 Mar 2014 06:26:49 +0000 Subject: [PATCH] Completely rewrite ELFObjectWriter::RecordRelocation. I started trying to fix a small issue, but this code has seen a small fix too many. The old code was fairly convoluted. Some of the issues it had: * It failed to check if a symbol difference was in the some section when converting a relocation to pcrel. * It failed to check if the relocation was already pcrel. * The pcrel value computation was wrong in some cases (relocation-pc.s) * It was missing quiet a few cases where it should not convert symbol relocations to section relocations, leaving the backends to patch it up. * It would not propagate the fact that it had changed a relocation to pcrel, requiring a quiet nasty work around in ARM. * It was missing comments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205076 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAsmBackend.h | 2 +- include/llvm/MC/MCAssembler.h | 4 +- include/llvm/MC/MCELFObjectWriter.h | 35 +- include/llvm/MC/MCMachObjectWriter.h | 3 +- include/llvm/MC/MCObjectWriter.h | 1 + lib/MC/ELFObjectWriter.cpp | 386 ++++++++++-------- lib/MC/MCAssembler.cpp | 20 +- lib/MC/MCELFObjectTargetWriter.cpp | 36 +- lib/MC/MachObjectWriter.cpp | 1 + lib/MC/WinCOFFObjectWriter.cpp | 4 +- .../MCTargetDesc/AArch64AsmBackend.cpp | 2 +- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 42 +- .../ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 104 +---- lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h | 9 - .../ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 43 +- .../ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 11 - .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 3 +- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h | 2 +- lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h | 28 -- .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 132 +----- .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 2 +- .../MCTargetDesc/PPCELFObjectWriter.cpp | 56 --- .../R600/MCTargetDesc/AMDGPUAsmBackend.cpp | 14 +- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 2 +- .../MCTargetDesc/SparcELFObjectWriter.cpp | 23 -- .../MCTargetDesc/SystemZMCAsmBackend.cpp | 5 +- .../MCTargetDesc/SystemZMCObjectWriter.cpp | 18 - lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 2 +- test/MC/ARM/arm-elf-symver.s | 33 +- test/MC/ELF/bad-expr2.s | 12 + test/MC/ELF/bad-expr3.s | 10 + test/MC/ELF/merge.s | 9 +- test/MC/ELF/relocation-386.s | 4 +- test/MC/ELF/relocation-pc.s | 4 +- 34 files changed, 359 insertions(+), 703 deletions(-) create mode 100644 test/MC/ELF/bad-expr2.s create mode 100644 test/MC/ELF/bad-expr3.s diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index c5f6a662097..82b65fdaf5c 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -97,7 +97,7 @@ public: /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const = 0; + uint64_t Value, bool IsPCRel) const = 0; /// @} diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 506e555e485..6cb6fd232a3 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -979,8 +979,8 @@ private: /// finishLayout - Finalize a layout, including fragment lowering. void finishLayout(MCAsmLayout &Layout); - uint64_t handleFixup(const MCAsmLayout &Layout, - MCFragment &F, const MCFixup &Fixup); + std::pair handleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); public: /// Compute the effective fragment size assuming it is laid out at the given diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 78435e6f47f..127f1624878 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,30 +20,10 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; +class MCSectionData; class MCSymbol; class MCValue; -/// @name Relocation Data -/// @{ - -struct ELFRelocationEntry { - // Make these big enough for both 32-bit and 64-bit - uint64_t r_offset; - int Index; - unsigned Type; - const MCSymbol *Symbol; - uint64_t r_addend; - const MCFixup *Fixup; - - ELFRelocationEntry() - : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0), Fixup(0) {} - - ELFRelocationEntry(uint64_t RelocOffset, int Idx, unsigned RelType, - const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) - : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), - r_addend(Addend), Fixup(&Fixup) {} -}; - class MCELFObjectTargetWriter { const uint8_t OSABI; const uint16_t EMachine; @@ -73,17 +53,8 @@ public: virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const = 0; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const; - - virtual void sortRelocs(const MCAssembler &Asm, - std::vector &Relocs); + + virtual bool needsRelocateWithSymbol(unsigned Type) const; /// @name Accessors /// @{ diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 644b44eceeb..e7d5bbd5be6 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -230,7 +230,8 @@ public: void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; void BindIndirectSymbols(MCAssembler &Asm); diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 4939a3f1fb0..55c828c6c17 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -80,6 +80,7 @@ public: const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4ebfc4de557..d8f03fcc58d 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -76,6 +76,27 @@ public: uint8_t other, uint32_t shndx, bool Reserved); }; +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + bool UseSymbol; // Relocate with a symbol, not the section. + union { + const MCSymbol *Symbol; // The symbol to relocate with. + const MCSectionData *Section; // The section to relocate with. + }; + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + + ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + uint64_t Addend) + : Offset(Offset), UseSymbol(true), Symbol(Symbol), Type(Type), + Addend(Addend) {} + + ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section, + unsigned Type, uint64_t Addend) + : Offset(Offset), UseSymbol(false), Section(Section), Type(Type), + Addend(Addend) {} +}; + class ELFObjectWriter : public MCObjectWriter { FragmentWriter FWriter; @@ -125,8 +146,8 @@ class ELFObjectWriter : public MCObjectWriter { SmallPtrSet WeakrefUsedInReloc; DenseMap Renames; - llvm::DenseMap > Relocations; + llvm::DenseMap> + Relocations; DenseMap SectionStringTableIndex; /// @} @@ -153,27 +174,7 @@ class ELFObjectWriter : public MCObjectWriter { unsigned ShstrtabIndex; - const MCSymbol *SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - // TargetObjectWriter wrappers. - const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); - } - const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, - IsPCRel); - } - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool hasRelocationAddend() const { return TargetObjectWriter->hasRelocationAddend(); @@ -213,9 +214,14 @@ class ELFObjectWriter : public MCObjectWriter { const MCAsmLayout &Layout, SectionIndexMapTy &SectionIndexMap); + bool shouldRelocateWithSymbol(const MCSymbolRefExpr *RefA, + const MCSymbolData *SD, uint64_t C, + unsigned Type) const; + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S); @@ -716,146 +722,186 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, } } -const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = Symbol.AliasedSymbol(); - const MCSymbol *Renamed = Renames.lookup(&Symbol); - const MCSymbolData &SD = Asm.getSymbolData(Symbol); - - if (ASymbol.isUndefined()) { - if (Renamed) - return Renamed; - return undefinedExplicitRelSym(Target, Fixup, IsPCRel); - } - - if (SD.isExternal()) { - if (Renamed) - return Renamed; - return &Symbol; - } - - const MCSectionELF &Section = - static_cast(ASymbol.getSection()); - const SectionKind secKind = Section.getKind(); +// It is always valid to create a relocation with a symbol. It is preferable +// to use a relocation with a section if that is possible. Using the section +// allows us to omit some local symbols from the symbol table. +bool ELFObjectWriter::shouldRelocateWithSymbol(const MCSymbolRefExpr *RefA, + const MCSymbolData *SD, + uint64_t C, + unsigned Type) const { + // A PCRel relocation to an absolute value has no symbol (or section). We + // represent that with a relocation to a null section. + if (!RefA) + return false; - if (secKind.isBSS()) - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); + MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); + switch (Kind) { + default: + break; + // The .odp creation emits a relocation against the symbol ".TOC." which + // create a R_PPC64_TOC relocation. However the relocation symbol name + // in final object creation should be NULL, since the symbol does not + // really exist, it is just the reference to TOC base for the current + // object file. Since the symbol is undefined, returning false results + // in a relocation with a null section which is the desired result. + case MCSymbolRefExpr::VK_PPC_TOCBASE: + return false; - if (secKind.isThreadLocal()) { - if (Renamed) - return Renamed; - return &Symbol; + // These VariantKind cause the relocation to refer to something other than + // the symbol itself, like a linker generated table. Since the address of + // symbol is not relevant, we cannot replace the symbol with the + // section and patch the difference in the addend. + case MCSymbolRefExpr::VK_GOT: + case MCSymbolRefExpr::VK_PLT: + case MCSymbolRefExpr::VK_GOTPCREL: + case MCSymbolRefExpr::VK_Mips_GOT: + case MCSymbolRefExpr::VK_PPC_GOT_LO: + case MCSymbolRefExpr::VK_PPC_GOT_HI: + case MCSymbolRefExpr::VK_PPC_GOT_HA: + return true; } - MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); - const MCSectionELF &Sec2 = - static_cast(F.getParent()->getSection()); + // An undefined symbol is not in any section, so the relocation has to point + // to the symbol itself. + const MCSymbol &Sym = SD->getSymbol(); + if (Sym.isUndefined()) + return true; - if (&Sec2 != &Section && - (Kind == MCSymbolRefExpr::VK_PLT || - Kind == MCSymbolRefExpr::VK_GOTPCREL || - Kind == MCSymbolRefExpr::VK_GOTOFF)) { - if (Renamed) - return Renamed; - return &Symbol; + unsigned Binding = MCELF::GetBinding(*SD); + switch(Binding) { + default: + llvm_unreachable("Invalid Binding"); + case ELF::STB_LOCAL: + break; + case ELF::STB_WEAK: + // If the symbol is weak, it might be overridden by a symbol in another + // file. The relocation has to point to the symbol so that the linker + // can update it. + return true; + case ELF::STB_GLOBAL: + // Global ELF symbols can be preempted by the dynamic linker. The relocation + // has to point to the symbol for a reason analogous to the STB_WEAK case. + return true; } - if (Section.getFlags() & ELF::SHF_MERGE) { - if (Target.getConstant() == 0) - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); - if (Renamed) - return Renamed; - return &Symbol; + // If a relocation points to a mergeable section, we have to be careful. + // If the offset is zero, a relocation with the section will encode the + // same information. With a non-zero offset, the situation is different. + // For example, a relocation can point 42 bytes past the end of a string. + // If we change such a relocation to use the section, the linker would think + // that it pointed to another string and subtracting 42 at runtime will + // produce the wrong value. + auto &Sec = cast(Sym.getSection()); + unsigned Flags = Sec.getFlags(); + if (Flags & ELF::SHF_MERGE) { + if (C != 0) + return true; } - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); + // Most TLS relocations use a got, so they need the symbol. Even those that + // are just an offset (@tpoff), require a symbol in some linkers (gold, + // but not bfd ld). + if (Flags & ELF::SHF_TLS) + return true; + if (TargetObjectWriter->needsRelocateWithSymbol(Type)) + return true; + return false; } - void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { - int64_t Addend = 0; - int Index = 0; - int64_t Value = Target.getConstant(); - const MCSymbol *RelocSymbol = NULL; - - bool IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - if (!Target.isAbsolute()) { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = Symbol.AliasedSymbol(); - RelocSymbol = SymbolToReloc(Asm, Target, *Fragment, Fixup, IsPCRel); - - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - const MCSymbol &SymbolB = RefB->getSymbol(); - MCSymbolData &SDB = Asm.getSymbolData(SymbolB); - IsPCRel = true; - - if (!SDB.getFragment()) - Asm.getContext().FatalError( - Fixup.getLoc(), - Twine("symbol '") + SymbolB.getName() + - "' can not be undefined in a subtraction expression"); - - // Offset of the symbol in the section - int64_t a = Layout.getSymbolOffset(&SDB); - - // Offset of the relocation in the section - int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - Value += b - a; - } + const MCSectionData *FixupSection = Fragment->getParent(); + uint64_t C = Target.getConstant(); + uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + assert(RefB->getKind() == MCSymbolRefExpr::VK_None && + "Should not have constructed this"); + + // Let A, B and C being the components of Target and R be the location of + // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). + // If it is pcrel, we want to compute (A - B + C - R). + + // In general, ELF has no relocations for -B. It can only represent (A + C) + // or (A + C - R). If B = R + K and the relocation is not pcrel, we can + // replace B to implement it: (A - R - K + C) + if (IsPCRel) + Asm.getContext().FatalError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + + const MCSymbol &SymB = RefB->getSymbol(); + + if (SymB.isUndefined()) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + SymB.getName() + + "' can not be undefined in a subtraction expression"); + + assert(!SymB.isAbsolute() && "Should have been folded"); + const MCSection &SecB = SymB.getSection(); + if (&SecB != &FixupSection->getSection()) + Asm.getContext().FatalError( + Fixup.getLoc(), "Cannot represent a difference across sections"); + + const MCSymbolData &SymBD = Asm.getSymbolData(SymB); + uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD); + uint64_t K = SymBOffset - FixupOffset; + IsPCRel = true; + C -= K; + } - if (!RelocSymbol) { - MCSymbolData &SD = Asm.getSymbolData(ASymbol); - MCFragment *F = SD.getFragment(); + // We either rejected the fixup or folded B into C at this point. + const MCSymbolRefExpr *RefA = Target.getSymA(); + const MCSymbol *SymA = RefA ? &RefA->getSymbol() : nullptr; + const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr; - if (F) { - Index = F->getParent()->getOrdinal() + 1; - // Offset of the symbol in the section - Value += Layout.getSymbolOffset(&SD); - } else { - Index = 0; - } - } else { - if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_WEAKREF) - WeakrefUsedInReloc.insert(RelocSymbol); - else - UsedInReloc.insert(RelocSymbol); - Index = -1; - } - Addend = Value; - if (hasRelocationAddend()) - Value = 0; + unsigned Type = GetRelocType(Target, Fixup, IsPCRel); + bool RelocateWithSymbol = shouldRelocateWithSymbol(RefA, SymAD, C, Type); + if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) + C += Layout.getSymbolOffset(SymAD); + + uint64_t Addend = 0; + if (hasRelocationAddend()) { + Addend = C; + C = 0; } - FixedValue = Value; - unsigned Type = GetRelocType(Target, Fixup, IsPCRel); - MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? - MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + FixedValue = C; + + // FIXME: What is this!?!? + MCSymbolRefExpr::VariantKind Modifier = + RefA ? RefA->getKind() : MCSymbolRefExpr::VK_None; if (RelocNeedsGOT(Modifier)) NeedsGOT = true; - uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + - Fixup.getOffset(); + if (!RelocateWithSymbol) { + const MCSection *SecA = + (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; + const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr; + ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend); + Relocations[FixupSection].push_back(Rec); + return; + } - if (!hasRelocationAddend()) - Addend = 0; + if (SymA) { + if (const MCSymbol *R = Renames.lookup(SymA)) + SymA = R; - if (is64Bit()) - assert(isInt<64>(Addend)); - else - assert(isInt<32>(Addend)); - - ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend, Fixup); - Relocations[Fragment->getParent()].push_back(ERE); + if (RefA->getKind() == MCSymbolRefExpr::VK_WEAKREF) + WeakrefUsedInReloc.insert(SymA); + else + UsedInReloc.insert(SymA); + } + ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend); + Relocations[FixupSection].push_back(Rec); + return; } @@ -1154,51 +1200,71 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, WriteWord(EntrySize); // sh_entsize } +// ELF doesn't require relocations to be in any order. We sort by the r_offset, +// just to match gnu as for easier comparison. The use type is an arbitrary way +// of making the sort deterministic. +static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { + const ELFRelocationEntry &A = *AP; + const ELFRelocationEntry &B = *BP; + if (A.Offset != B.Offset) + return B.Offset - A.Offset; + if (B.Type != A.Type) + return A.Type - B.Type; + llvm_unreachable("ELFRelocs might be unstable!"); +} + +static void sortRelocs(const MCAssembler &Asm, + std::vector &Relocs) { + array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); +} + void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, const MCSectionData *SD) { std::vector &Relocs = Relocations[SD]; - // Sort the relocation entries. Most targets just sort by r_offset, but some - // (e.g., MIPS) have additional constraints. - TargetObjectWriter->sortRelocs(Asm, Relocs); + sortRelocs(Asm, Relocs); for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - ELFRelocationEntry entry = Relocs[e - i - 1]; + const ELFRelocationEntry &Entry = Relocs[e - i - 1]; + + unsigned Index; + if (Entry.UseSymbol) { + Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol); + } else { + const MCSectionData *Sec = Entry.Section; + if (Sec) + Index = Sec->getOrdinal() + FileSymbolData.size() + + LocalSymbolData.size() + 1; + else + Index = 0; + } - if (!entry.Index) - ; - // FIXME: this is most likely a bug if index overflows. - else if (entry.Index < 0) - entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); - else - entry.Index += FileSymbolData.size() + LocalSymbolData.size(); if (is64Bit()) { - write(*F, entry.r_offset); + write(*F, Entry.Offset); if (TargetObjectWriter->isN64()) { - write(*F, uint32_t(entry.Index)); + write(*F, uint32_t(Index)); - write(*F, TargetObjectWriter->getRSsym(entry.Type)); - write(*F, TargetObjectWriter->getRType3(entry.Type)); - write(*F, TargetObjectWriter->getRType2(entry.Type)); - write(*F, TargetObjectWriter->getRType(entry.Type)); - } - else { + write(*F, TargetObjectWriter->getRSsym(Entry.Type)); + write(*F, TargetObjectWriter->getRType3(Entry.Type)); + write(*F, TargetObjectWriter->getRType2(Entry.Type)); + write(*F, TargetObjectWriter->getRType(Entry.Type)); + } else { struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(entry.Index, entry.Type); + ERE64.setSymbolAndType(Index, Entry.Type); write(*F, ERE64.r_info); } if (hasRelocationAddend()) - write(*F, entry.r_addend); + write(*F, Entry.Addend); } else { - write(*F, uint32_t(entry.r_offset)); + write(*F, uint32_t(Entry.Offset)); struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(entry.Index, entry.Type); + ERE32.setSymbolAndType(Index, Entry.Type); write(*F, ERE32.r_info); if (hasRelocationAddend()) - write(*F, uint32_t(entry.r_addend)); + write(*F, uint32_t(Entry.Addend)); } } } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index fcf1b50a4f7..5536087bd0c 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -779,20 +779,22 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, Layout.getSectionAddressSize(SD)); } - -uint64_t MCAssembler::handleFixup(const MCAsmLayout &Layout, - MCFragment &F, - const MCFixup &Fixup) { +std::pair MCAssembler::handleFixup(const MCAsmLayout &Layout, + MCFragment &F, + const MCFixup &Fixup) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; + bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsPCRel; if (!evaluateFixup(Layout, Fixup, &F, 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. - getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); + getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel, + FixedValue); } - return FixedValue; + return std::make_pair(FixedValue, IsPCRel); } void MCAssembler::Finish() { @@ -856,9 +858,11 @@ void MCAssembler::Finish() { for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), ie3 = F->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; - uint64_t FixedValue = handleFixup(Layout, *F, Fixup); + uint64_t FixedValue; + bool IsPCRel; + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); getBackend().applyFixup(Fixup, F->getContents().data(), - F->getContents().size(), FixedValue); + F->getContents().size(), FixedValue, IsPCRel); } } } diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp index 0c39e4a17ef..4012c442e4f 100644 --- a/lib/MC/MCELFObjectTargetWriter.cpp +++ b/lib/MC/MCELFObjectTargetWriter.cpp @@ -24,38 +24,6 @@ MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, IsN64(IsN64_){ } -const MCSymbol *MCELFObjectTargetWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - return NULL; -} - -const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - return &Symbol.AliasedSymbol(); -} - -// ELF doesn't require relocations to be in any order. We sort by the r_offset, -// just to match gnu as for easier comparison. The use type and index is an -// arbitrary way of making the sort deterministic. -static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { - const ELFRelocationEntry &A = *AP; - const ELFRelocationEntry &B = *BP; - if (A.r_offset != B.r_offset) - return B.r_offset - A.r_offset; - if (B.Type != A.Type) - return A.Type - B.Type; - if (B.Index != A.Index) - return B.Index - A.Index; - llvm_unreachable("ELFRelocs might be unstable!"); -} - -void -MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm, - std::vector &Relocs) { - array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); +bool MCELFObjectTargetWriter::needsRelocateWithSymbol(unsigned Type) const { + return false; } diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index ff55c978d6a..bbe589f3385 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -417,6 +417,7 @@ void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup, Target, FixedValue); diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index e41a6bdfca7..500acd8f14e 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -172,7 +172,8 @@ public: void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; }; @@ -656,6 +657,7 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { assert(Target.getSymA() != NULL && "Relocation must reference a symbol!"); diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index 4e6af63382d..f1452ab428f 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -177,7 +177,7 @@ public: } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const { + uint64_t Value, bool IsPCRel) const { unsigned NumBytes = getFixupKindInfo(Fixup.getKind()).TargetSize / 8; Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 824dee00c2a..19c717f5f83 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -97,10 +97,6 @@ public: { "fixup_arm_movw_lo16", 0, 20, 0 }, { "fixup_t2_movt_hi16", 0, 20, 0 }, { "fixup_t2_movw_lo16", 0, 20, 0 }, -{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, }; const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = { // This table *must* be in the order that the fixup_* kinds are defined in @@ -138,10 +134,6 @@ public: { "fixup_arm_movw_lo16", 12, 20, 0 }, { "fixup_t2_movt_hi16", 12, 20, 0 }, { "fixup_t2_movw_lo16", 12, 20, 0 }, -{ "fixup_arm_movt_hi16_pcrel", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_arm_movw_lo16_pcrel", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movt_hi16_pcrel", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_movw_lo16_pcrel", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, }; if (Kind < FirstTargetFixupKind) @@ -161,7 +153,7 @@ public: void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const override; + uint64_t Value, bool IsPCRel) const override; bool mayNeedRelaxation(const MCInst &Inst) const override; @@ -315,7 +307,7 @@ bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { } static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext *Ctx = NULL) { + bool IsPCRel, MCContext *Ctx) { unsigned Kind = Fixup.getKind(); switch (Kind) { default: @@ -325,11 +317,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case FK_Data_4: return Value; case ARM::fixup_arm_movt_hi16: - Value >>= 16; + if (!IsPCRel) + Value >>= 16; // Fallthrough - case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_arm_movw_lo16_pcrel: { + case ARM::fixup_arm_movw_lo16: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned Lo12 = Value & 0x0FFF; // inst{19-16} = Hi4; @@ -338,12 +329,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return Value; } case ARM::fixup_t2_movt_hi16: - Value >>= 16; + if (!IsPCRel) + Value >>= 16; // Fallthrough - case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like - // the other hi16 fixup? - case ARM::fixup_t2_movw_lo16_pcrel: { + case ARM::fixup_t2_movw_lo16: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned i = (Value & 0x800) >> 11; unsigned Mid3 = (Value & 0x700) >> 8; @@ -629,7 +618,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, // Try to get the encoded value for the fixup as-if we're mapping it into // the instruction. This allows adjustFixupValue() to issue a diagnostic // if the value aren't invalid. - (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); + (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext()); } /// getFixupKindNumBytes - The number of bytes the fixup may change. @@ -670,12 +659,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case ARM::fixup_arm_thumb_blx: case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movt_hi16: case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: - case ARM::fixup_t2_movw_lo16_pcrel: return 4; } } @@ -720,21 +705,18 @@ static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { case ARM::fixup_arm_thumb_blx: case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movt_hi16_pcrel: - case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movt_hi16: case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: - case ARM::fixup_t2_movw_lo16_pcrel: // Instruction size is 4 bytes. return 4; } } void ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); - Value = adjustFixupValue(Fixup, Value); + Value = adjustFixupValue(Fixup, Value, IsPCRel, nullptr); if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index 44c57312829..a4661b1a4fb 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -36,10 +36,8 @@ namespace { unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const override; + + bool needsRelocateWithSymbol(unsigned Type) const override; }; } @@ -50,90 +48,18 @@ ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) ARMELFObjectWriter::~ARMELFObjectWriter() {} -// In ARM, _MergedGlobals and other most symbols get emitted directly. -// I.e. not as an offset to a section symbol. -// This code is an approximation of what ARM/gcc does. - -STATISTIC(PCRelCount, "Total number of PIC Relocations"); -STATISTIC(NonPCRelCount, "Total number of non-PIC relocations"); - -const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); - bool EmitThisSym = false; - - const MCSectionELF &Section = - static_cast(Symbol.getSection()); - bool InNormalSection = true; - unsigned RelocType = 0; - RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel); - assert(!Target.getSymB() || - Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None); - - DEBUG( - MCSymbolRefExpr::VariantKind Kind = Fixup.getAccessVariant(); - dbgs() << "considering symbol " - << Section.getSectionName() << "/" - << Symbol.getName() << "/" - << " Rel:" << (unsigned)RelocType - << " Kind: " << (int)Kind - << " Tmp:" - << Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/" - << Symbol.isVariable() << "/" << Symbol.isTemporary() - << " Counts:" << PCRelCount << "/" << NonPCRelCount << "\n"); - - if (IsPCRel) { ++PCRelCount; - switch (RelocType) { - default: - // Most relocation types are emitted as explicit symbols - InNormalSection = - StringSwitch(Section.getSectionName()) - .Case(".data.rel.ro.local", false) - .Case(".data.rel", false) - .Case(".bss", false) - .Default(true); - EmitThisSym = true; - break; - case ELF::R_ARM_ABS32: - // But things get strange with R_ARM_ABS32 - // In this case, most things that go in .rodata show up - // as section relative relocations - InNormalSection = - StringSwitch(Section.getSectionName()) - .Case(".data.rel.ro.local", false) - .Case(".data.rel", false) - .Case(".rodata", false) - .Case(".bss", false) - .Default(true); - EmitThisSym = false; - break; - } - } else { - NonPCRelCount++; - InNormalSection = - StringSwitch(Section.getSectionName()) - .Case(".data.rel.ro.local", false) - .Case(".rodata", false) - .Case(".data.rel", false) - .Case(".bss", false) - .Default(true); - - switch (RelocType) { - default: EmitThisSym = true; break; - case ELF::R_ARM_ABS32: EmitThisSym = false; break; - case ELF::R_ARM_PREL31: EmitThisSym = false; break; - } - } - - if (EmitThisSym) - return &Symbol; - if (! Symbol.isTemporary() && InNormalSection) { - return &Symbol; +bool ARMELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { + // FIXME: This is extremelly conservative. This really needs to use a + // whitelist with a clear explanation for why each realocation needs to + // point to the symbol, not to the section. + switch (Type) { + default: + return true; + + case ELF::R_ARM_PREL31: + case ELF::R_ARM_ABS32: + return false; } - return NULL; } // Need to examine the Fixup when determining whether to @@ -191,19 +117,15 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, Type = ELF::R_ARM_THM_JUMP24; break; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: Type = ELF::R_ARM_MOVT_PREL; break; case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: Type = ELF::R_ARM_MOVW_PREL_NC; break; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: Type = ELF::R_ARM_THM_MOVT_PREL; break; case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: Type = ELF::R_ARM_THM_MOVW_PREL_NC; break; case ARM::fixup_arm_thumb_bl: diff --git a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h index 0085feb8206..bfd9e336482 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h +++ b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h @@ -100,15 +100,6 @@ enum Fixups { fixup_t2_movt_hi16, // :upper16: fixup_t2_movw_lo16, // :lower16: - // It is possible to create an "immediate" that happens to be pcrel. - // movw r0, :lower16:Foo-(Bar+8) and movt r0, :upper16:Foo-(Bar+8) - // result in different reloc tags than the above two. - // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC - fixup_arm_movt_hi16_pcrel, // :upper16: - fixup_arm_movw_lo16_pcrel, // :lower16: - fixup_t2_movt_hi16_pcrel, // :upper16: - fixup_t2_movw_lo16_pcrel, // :lower16: - // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 260201cbcb0..12cd33676a8 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -975,19 +975,6 @@ getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, return (Reg << 8) | Imm8; } -// FIXME: This routine assumes that a binary -// expression will always result in a PCRel expression -// In reality, its only true if one or more subexpressions -// is itself a PCRel (i.e. "." in asm or some other pcrel construct) -// but this is good enough for now. -static bool EvaluateAsPCRel(const MCExpr *Expr) { - switch (Expr->getKind()) { - default: llvm_unreachable("Unexpected expression type"); - case MCExpr::SymbolRef: return false; - case MCExpr::Binary: return true; - } -} - uint32_t ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, @@ -1023,24 +1010,12 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, switch (ARM16Expr->getKind()) { default: llvm_unreachable("Unsupported ARMFixup"); case ARMMCExpr::VK_ARM_HI16: - if (!isTargetMachO(STI) && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movt_hi16_pcrel - : ARM::fixup_arm_movt_hi16_pcrel); - else - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movt_hi16 - : ARM::fixup_arm_movt_hi16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movt_hi16 + : ARM::fixup_arm_movt_hi16); break; case ARMMCExpr::VK_ARM_LO16: - if (!isTargetMachO(STI) && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movw_lo16_pcrel - : ARM::fixup_arm_movw_lo16_pcrel); - else - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movw_lo16 - : ARM::fixup_arm_movw_lo16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movw_lo16 + : ARM::fixup_arm_movw_lo16); break; } Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); @@ -1050,14 +1025,8 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, // it's just a plain immediate expression, and those evaluate to // the lower 16 bits of the expression regardless of whether // we have a movt or a movw. - if (!isTargetMachO(STI) && EvaluateAsPCRel(E)) - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movw_lo16_pcrel - : ARM::fixup_arm_movw_lo16_pcrel); - else - Kind = MCFixupKind(isThumb2(STI) - ? ARM::fixup_t2_movw_lo16 - : ARM::fixup_arm_movw_lo16); + Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movw_lo16 + : ARM::fixup_arm_movw_lo16); Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); return 0; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp index 4c8702c6e3d..3bf5cf11d51 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp @@ -123,23 +123,19 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, // 0 - arm instructions // 1 - thumb instructions case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 1; return true; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 3; return true; case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 0; return true; case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: RelocType = unsigned(MachO::ARM_RELOC_HALF); Log2Size = 2; return true; @@ -206,7 +202,6 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, switch ((unsigned)Fixup.getKind()) { default: break; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: MovtBit = 1; // The thumb bit shouldn't be set in the 'other-half' bit of the // relocation, but it will be set in FixedValue if the base symbol @@ -215,13 +210,11 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, FixedValue &= 0xfffffffe; break; case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: if (A_SD->getFlags() & SF_ThumbFunc) FixedValue &= 0xfffffffe; MovtBit = 1; // Fallthrough case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: ThumbBit = 1; break; } @@ -465,15 +458,11 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, switch ((unsigned)Fixup.getKind()) { default: break; case ARM::fixup_arm_movw_lo16: - case ARM::fixup_arm_movw_lo16_pcrel: case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movw_lo16_pcrel: Value = (FixedValue >> 16) & 0xffff; break; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movt_hi16_pcrel: case ARM::fixup_t2_movt_hi16: - case ARM::fixup_t2_movt_hi16_pcrel: Value = FixedValue & 0xffff; break; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 190aa1420ef..541f8b6f918 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -116,7 +116,8 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const { /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { MCFixupKind Kind = Fixup.getKind(); Value = adjustFixupValue(Fixup, Value); diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index e827fdf1892..cc5207a3bb7 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -40,7 +40,7 @@ public: MCObjectWriter *createObjectWriter(raw_ostream &OS) const; void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const; + uint64_t Value, bool IsPCRel) const; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 7a55efd5c33..d2323dc1b47 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -120,34 +120,6 @@ namespace MipsII { FormMask = 15 }; } - -inline static std::pair -MipsGetSymAndOffset(const MCFixup &Fixup) { - MCFixupKind FixupKind = Fixup.getKind(); - - if ((FixupKind < FirstTargetFixupKind) || - (FixupKind >= MCFixupKind(Mips::LastTargetFixupKind))) - return std::make_pair((const MCSymbolRefExpr*)0, (int64_t)0); - - const MCExpr *Expr = Fixup.getValue(); - MCExpr::ExprKind Kind = Expr->getKind(); - - if (Kind == MCExpr::Binary) { - const MCBinaryExpr *BE = static_cast(Expr); - const MCExpr *LHS = BE->getLHS(); - const MCConstantExpr *CE = dyn_cast(BE->getRHS()); - - if ((LHS->getKind() != MCExpr::SymbolRef) || !CE) - return std::make_pair((const MCSymbolRefExpr*)0, (int64_t)0); - - return std::make_pair(cast(LHS), CE->getValue()); - } - - if (Kind != MCExpr::SymbolRef) - return std::make_pair((const MCSymbolRefExpr*)0, (int64_t)0); - - return std::make_pair(cast(Expr), 0); -} } #endif diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index ce763367e29..f933962d664 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -21,17 +21,6 @@ using namespace llvm; namespace { - struct RelEntry { - RelEntry(const ELFRelocationEntry &R, const MCSymbol *S, int64_t O) : - Reloc(R), Sym(S), Offset(O) {} - ELFRelocationEntry Reloc; - const MCSymbol *Sym; - int64_t Offset; - }; - - typedef std::list RelLs; - typedef RelLs::iterator RelLsIter; - class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, @@ -41,13 +30,7 @@ namespace { unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - virtual void sortRelocs(const MCAssembler &Asm, - std::vector &Relocs); + bool needsRelocateWithSymbol(unsigned Type) const override; }; } @@ -59,21 +42,6 @@ MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, MipsELFObjectWriter::~MipsELFObjectWriter() {} -const MCSymbol *MipsELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - assert(Target.getSymA() && "SymA cannot be 0."); - const MCSymbol &Sym = Target.getSymA()->getSymbol().AliasedSymbol(); - - if (Sym.getSection().getKind().isMergeableCString() || - Sym.getSection().getKind().isMergeableConst()) - return &Sym; - - return NULL; -} - unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { @@ -229,91 +197,23 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, return Type; } -// Return true if R is either a GOT16 against a local symbol or HI16. -static bool NeedsMatchingLo(const MCAssembler &Asm, const RelEntry &R) { - if (!R.Sym) - return false; - - MCSymbolData &SD = Asm.getSymbolData(R.Sym->AliasedSymbol()); - - return ((R.Reloc.Type == ELF::R_MIPS_GOT16) && !SD.isExternal()) || - (R.Reloc.Type == ELF::R_MIPS_HI16); -} - -static bool HasMatchingLo(const MCAssembler &Asm, RelLsIter I, RelLsIter Last) { - if (I == Last) +bool +MipsELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { + // FIXME: This is extremelly conservative. This really needs to use a + // whitelist with a clear explanation for why each realocation needs to + // point to the symbol, not to the section. + switch (Type) { + default: + return true; + + case ELF::R_MIPS_26: + case ELF::R_MIPS_LO16: + case ELF::R_MIPS_HI16: + case ELF::R_MIPS_32: + case ELF::R_MIPS_64: + case ELF::R_MIPS_GPREL16: return false; - - RelLsIter Hi = I++; - - return (I->Reloc.Type == ELF::R_MIPS_LO16) && (Hi->Sym == I->Sym) && - (Hi->Offset == I->Offset); -} - -static bool HasSameSymbol(const RelEntry &R0, const RelEntry &R1) { - return R0.Sym == R1.Sym; -} - -static int CompareOffset(const RelEntry &R0, const RelEntry &R1) { - return (R0.Offset > R1.Offset) ? 1 : ((R0.Offset == R1.Offset) ? 0 : -1); -} - -void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, - std::vector &Relocs) { - // Call the default function first. Relocations are sorted in descending - // order of r_offset. - MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); - - RelLs RelocLs; - std::vector Unmatched; - - // Fill RelocLs. Traverse Relocs backwards so that relocations in RelocLs - // are in ascending order of r_offset. - for (std::vector::reverse_iterator R = Relocs.rbegin(); - R != Relocs.rend(); ++R) { - std::pair P = - MipsGetSymAndOffset(*R->Fixup); - RelocLs.push_back(RelEntry(*R, P.first ? &P.first->getSymbol() : 0, - P.second)); } - - // Get list of unmatched HI16 and GOT16. - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) - if (NeedsMatchingLo(Asm, *R) && !HasMatchingLo(Asm, R, --RelocLs.end())) - Unmatched.push_back(R); - - // Insert unmatched HI16 and GOT16 immediately before their matching LO16. - for (std::vector::iterator U = Unmatched.begin(); - U != Unmatched.end(); ++U) { - RelLsIter LoPos = RelocLs.end(), HiPos = *U; - bool MatchedLo = false; - - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) { - if ((R->Reloc.Type == ELF::R_MIPS_LO16) && HasSameSymbol(*HiPos, *R) && - (CompareOffset(*R, *HiPos) >= 0) && - ((LoPos == RelocLs.end()) || ((CompareOffset(*R, *LoPos) < 0)) || - (!MatchedLo && !CompareOffset(*R, *LoPos)))) - LoPos = R; - - MatchedLo = NeedsMatchingLo(Asm, *R) && - HasMatchingLo(Asm, R, --RelocLs.end()); - } - - // If a matching LoPos was found, move HiPos and insert it before LoPos. - // Make the offsets of HiPos and LoPos match. - if (LoPos != RelocLs.end()) { - HiPos->Offset = LoPos->Offset; - RelocLs.insert(LoPos, *HiPos); - RelocLs.erase(HiPos); - } - } - - // Put the sorted list back in reverse order. - assert(Relocs.size() == RelocLs.size()); - unsigned I = RelocLs.size(); - - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) - Relocs[--I] = R->Reloc; } MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index f99bc7eb551..f7309bbf0ad 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -110,7 +110,7 @@ public: } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const { + uint64_t Value, bool IsPCRel) const { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index b5c5e194fec..d19f6a0214d 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -30,14 +30,6 @@ namespace { bool IsPCRel) const; unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const; }; } @@ -386,54 +378,6 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, return getRelocTypeInner(Target, Fixup, IsPCRel); } -const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - assert(Target.getSymA() && "SymA cannot be 0"); - MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant(); - - bool EmitThisSym; - switch (Modifier) { - // GOT references always need a relocation, even if the - // target symbol is local. - case MCSymbolRefExpr::VK_GOT: - case MCSymbolRefExpr::VK_PPC_GOT_LO: - case MCSymbolRefExpr::VK_PPC_GOT_HI: - case MCSymbolRefExpr::VK_PPC_GOT_HA: - EmitThisSym = true; - break; - default: - EmitThisSym = false; - break; - } - - if (EmitThisSym) - return &Target.getSymA()->getSymbol().AliasedSymbol(); - return NULL; -} - -const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - assert(Target.getSymA() && "SymA cannot be 0"); - const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); - - unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel); - - // The .odp creation emits a relocation against the symbol ".TOC." which - // create a R_PPC64_TOC relocation. However the relocation symbol name - // in final object creation should be NULL, since the symbol does not - // really exist, it is just the reference to TOC base for the current - // object file. - bool EmitThisSym = RelocType != ELF::R_PPC64_TOC; - - if (EmitThisSym && !Symbol.isTemporary()) - return &Symbol; - return NULL; -} - MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, bool IsLittleEndian, diff --git a/lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp b/lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp index 29d0acf9ea4..a6bb59f3a04 100644 --- a/lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp +++ b/lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp @@ -27,11 +27,10 @@ public: const MCAsmLayout &Layout) { //XXX: Implement if necessary. } - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) { + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override { assert(!"Not implemented"); } @@ -46,7 +45,7 @@ public: virtual unsigned getNumFixupKinds() const { return 0; }; virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const; + uint64_t Value, bool IsPCRel) const; virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const { @@ -71,7 +70,8 @@ void AMDGPUMCObjectWriter::WriteObject(MCAssembler &Asm, } void AMDGPUAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { uint16_t *Dst = (uint16_t*)(Data + Fixup.getOffset()); assert(Fixup.getKind() == FK_PCRel_4); diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index bf395154cce..39c99964599 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -229,7 +229,7 @@ namespace { SparcAsmBackend(T), OSType(OSType) { } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const { + uint64_t Value, bool IsPCRel) const { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. diff --git a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp index bb93b904ca0..5ba82f137b8 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -30,12 +30,6 @@ namespace { protected: unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; }; } @@ -110,23 +104,6 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, return ELF::R_SPARC_NONE; } -const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - - if (!Target.getSymA()) - return NULL; - switch((unsigned)Fixup.getKind()) { - default: break; - case Sparc::fixup_sparc_got22: - case Sparc::fixup_sparc_got10: - return &Target.getSymA()->getSymbol().AliasedSymbol(); - } - return NULL; -} - MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI) { diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp index 047a9764380..6e7268de55c 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -48,7 +48,7 @@ public: } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const override; + uint64_t Value, bool IsPCRel) const override; bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } @@ -85,7 +85,8 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { } void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { MCFixupKind Kind = Fixup.getKind(); unsigned Offset = Fixup.getOffset(); unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8; diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp index 76e1d24a937..54c6987ca2f 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp @@ -26,9 +26,6 @@ protected: // Override MCELFObjectTargetWriter. unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, const MCValue &Target, - const MCFragment &F, const MCFixup &Fixup, - bool IsPCRel) const override; }; } // end anonymous namespace @@ -111,21 +108,6 @@ unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, } } -const MCSymbol *SystemZObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - // The addend in a PC-relative R_390_* relocation is always applied to - // the PC-relative part of the address. If some kind of indirection - // is applied to the symbol first, we can't use an addend there too. - if (!Target.isAbsolute() && - Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None && - IsPCRel) - return &Target.getSymA()->getSymbol().AliasedSymbol(); - return NULL; -} - MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, uint8_t OSABI) { MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 3063ec61373..23763f7252f 100644 --- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -100,7 +100,7 @@ public: } void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const override { + uint64_t Value, bool IsPCRel) const override { unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind()); assert(Fixup.getOffset() + Size <= DataSize && diff --git a/test/MC/ARM/arm-elf-symver.s b/test/MC/ARM/arm-elf-symver.s index f7c0288a88f..5fb1f6a0f3e 100644 --- a/test/MC/ARM/arm-elf-symver.s +++ b/test/MC/ARM/arm-elf-symver.s @@ -24,16 +24,16 @@ global1: @ CHECK: Relocations [ @ CHECK-NEXT: Section (2) .rel.text { -@ CHECK-NEXT: 0x0 R_ARM_ABS32 defined1 0x0 +@ CHECK-NEXT: 0x0 R_ARM_ABS32 .text 0x0 @ CHECK-NEXT: 0x4 R_ARM_ABS32 bar2@zed 0x0 -@ CHECK-NEXT: 0x8 R_ARM_ABS32 defined2 0x0 -@ CHECK-NEXT: 0xC R_ARM_ABS32 defined3 0x0 +@ CHECK-NEXT: 0x8 R_ARM_ABS32 .text 0x0 +@ CHECK-NEXT: 0xC R_ARM_ABS32 .text 0x0 @ CHECK-NEXT: 0x10 R_ARM_ABS32 bar6@zed 0x0 @ CHECK-NEXT: } @ CHECK-NEXT: ] @ CHECK: Symbol { -@ CHECK: Name: bar1@zed (28) +@ CHECK: Name: bar1@zed @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Local (0x0) @@ -42,7 +42,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: bar3@@zed (46) +@ CHECK-NEXT: Name: bar3@@zed @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Local (0x0) @@ -51,7 +51,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: bar5@@zed (56) +@ CHECK-NEXT: Name: bar5@@zed @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Local (0x0) @@ -60,7 +60,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: defined1 (1) +@ CHECK-NEXT: Name: defined1 @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Local (0x0) @@ -69,16 +69,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: defined2 (10) -@ CHECK-NEXT: Value: 0x0 -@ CHECK-NEXT: Size: 0 -@ CHECK-NEXT: Binding: Local (0x0) -@ CHECK-NEXT: Type: None (0x0) -@ CHECK-NEXT: Other: 0 -@ CHECK-NEXT: Section: .text (0x1) -@ CHECK-NEXT: } -@ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: defined3 (19) +@ CHECK-NEXT: Name: defined2 @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Local (0x0) @@ -114,7 +105,7 @@ global1: @ CHECK-NEXT: Section: .bss (0x4) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: g1@@zed (88) +@ CHECK-NEXT: Name: g1@@zed @ CHECK-NEXT: Value: 0x14 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Global (0x1) @@ -123,7 +114,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: global1 (80) +@ CHECK-NEXT: Name: global1 @ CHECK-NEXT: Value: 0x14 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Global (0x1) @@ -132,7 +123,7 @@ global1: @ CHECK-NEXT: Section: .text (0x1) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: bar2@zed (37) +@ CHECK-NEXT: Name: bar2@zed @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Global (0x1) @@ -141,7 +132,7 @@ global1: @ CHECK-NEXT: Section: Undefined (0x0) @ CHECK-NEXT: } @ CHECK-NEXT: Symbol { -@ CHECK-NEXT: Name: bar6@zed (66) +@ CHECK-NEXT: Name: bar6@zed @ CHECK-NEXT: Value: 0x0 @ CHECK-NEXT: Size: 0 @ CHECK-NEXT: Binding: Global (0x1) diff --git a/test/MC/ELF/bad-expr2.s b/test/MC/ELF/bad-expr2.s new file mode 100644 index 00000000000..3da916b7fa1 --- /dev/null +++ b/test/MC/ELF/bad-expr2.s @@ -0,0 +1,12 @@ +// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o /dev/null \ +// RUN: 2>&1 | FileCheck %s + +// CHECK: No relocation available to represent this relative expression +// CHECK: call foo - bar + + + call foo - bar + .section .foo +foo: + .section .bar +bar: diff --git a/test/MC/ELF/bad-expr3.s b/test/MC/ELF/bad-expr3.s new file mode 100644 index 00000000000..990167cda53 --- /dev/null +++ b/test/MC/ELF/bad-expr3.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o /dev/null \ +// RUN: 2>&1 | FileCheck %s + +// CHECK: Cannot represent a difference across sections + + .long foo - bar + .section .zed +foo: + .section .bah +bar: diff --git a/test/MC/ELF/merge.s b/test/MC/ELF/merge.s index 0e92583192d..d6e0b7c4b7d 100644 --- a/test/MC/ELF/merge.s +++ b/test/MC/ELF/merge.s @@ -1,10 +1,7 @@ // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -r | FileCheck %s -// Test that PIC relocations with local symbols in a mergeable section are done -// with a reference to the symbol. Not sure if this is a linker limitation, -// but this matches the behavior of gas. - -// Non-PIC relocations with 0 offset don't use the symbol. +// Test that relocations with local symbols in a mergeable section are done +// with a reference to the symbol if the offset is non zero. movsd .Lfoo(%rip), %xmm1 @@ -13,6 +10,7 @@ jmp foo@PLT movq foo@GOTPCREL, %rax movq zed, %rax + movsd .Lfoo+4(%rip), %xmm1 .section .sec1,"aM",@progbits,16 .Lfoo: @@ -30,5 +28,6 @@ foo: // CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_PLT32 foo 0x{{[^ ]+}} // CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_GOTPCREL foo 0x{{[^ ]+}} // CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_32S zed 0x{{[^ ]+}} +// CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_PC32 .sec1 0x{{[^ ]+}} // CHECK-NEXT: } // CHECK-NEXT: ] diff --git a/test/MC/ELF/relocation-386.s b/test/MC/ELF/relocation-386.s index e8c31fc85ce..1409465b73e 100644 --- a/test/MC/ELF/relocation-386.s +++ b/test/MC/ELF/relocation-386.s @@ -5,7 +5,7 @@ // CHECK: Relocations [ // CHECK-NEXT: Section (2) .rel.text { -// CHECK-NEXT: 0x2 R_386_GOTOFF .Lfoo 0x0 +// CHECK-NEXT: 0x2 R_386_GOTOFF .rodata.str1.16 0x0 // CHECK-NEXT: 0x{{[^ ]+}} R_386_PLT32 bar2 0x0 // CHECK-NEXT: 0x{{[^ ]+}} R_386_GOTPC _GLOBAL_OFFSET_TABLE_ 0x0 // Relocation 3 (bar3@GOTOFF) is done with symbol 7 (bss) @@ -67,7 +67,7 @@ // Symbol 4 is zed // CHECK: Symbol { -// CHECK: Name: zed (53) +// CHECK: Name: zed // CHECK-NEXT: Value: 0x0 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Local diff --git a/test/MC/ELF/relocation-pc.s b/test/MC/ELF/relocation-pc.s index fc7420c3989..0ce32010cf0 100644 --- a/test/MC/ELF/relocation-pc.s +++ b/test/MC/ELF/relocation-pc.s @@ -26,7 +26,7 @@ // CHECK-NEXT: AddressAlignment: 8 // CHECK-NEXT: EntrySize: 24 // CHECK-NEXT: Relocations [ -// CHECK-NEXT: 0x1 R_X86_64_PC8 - 0x0 -// CHECK-NEXT: 0x3 R_X86_64_PC32 - 0x0 +// CHECK-NEXT: 0x1 R_X86_64_PC8 - 0xFFFFFFFFFFFFFFFF +// CHECK-NEXT: 0x3 R_X86_64_PC32 - 0xFFFFFFFFFFFFFEFC // CHECK-NEXT: ] // CHECK-NEXT: } -- 2.34.1