Add r224985 back with two fixes.

One is that AArch64 has additional restrictions on when local relocations can
be used. We have to take those into consideration when deciding to put a L
symbol in the symbol table or not.

The other is that ld64 requires the relocations to cstring to use linker
visible symbols on AArch64.

Thanks to Michael Zolotukhin for testing this!

Remove doesSectionRequireSymbols.

In an assembly expression like

bar:
.long L0 + 1

the intended semantics is that bar will contain a pointer one byte past L0.

In sections that are merged by content (strings, 4 byte constants, etc), a
single position in the section doesn't give the linker enough information.
For example, it would not be able to tell a relocation must point to the
end of a string, since that would look just like the start of the next.

The solution used in ELF to use relocation with symbols if there is a non-zero
addend.

In MachO before this patch we would just keep all symbols in some sections.

This would miss some cases (only cstrings on x86_64 were implemented) and was
inefficient since most relocations have an addend of 0 and can be represented
without the symbol.

This patch implements the non-zero addend logic for MachO too.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225644 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2015-01-12 18:13:07 +00:00
parent e5e4a9a4df
commit 5512415ade
19 changed files with 316 additions and 246 deletions

View File

@ -61,12 +61,6 @@ public:
/// markers. If not, data region directives will be ignored.
bool hasDataInCodeSupport() const { return HasDataInCodeSupport; }
/// doesSectionRequireSymbols - Check whether the given section requires that
/// all symbols (even temporaries) have symbol table entries.
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
return false;
}
/// @name Target Fixup Interfaces
/// @{

View File

@ -11,6 +11,7 @@
#define LLVM_MC_MCASSEMBLER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@ -881,6 +882,8 @@ private:
iplist<MCSymbolData> Symbols;
DenseSet<const MCSymbol *> LocalsUsedInReloc;
/// The map of sections to their associated assembler backend data.
//
// FIXME: Avoid this indirection?
@ -980,6 +983,9 @@ private:
MCFragment &F, const MCFixup &Fixup);
public:
void addLocalUsedInReloc(const MCSymbol &Sym);
bool isLocalUsedInReloc(const MCSymbol &Sym) const;
/// Compute the effective fragment size assuming it is laid out at the given
/// \p SectionAddress and \p FragmentOffset.
uint64_t computeFragmentSize(const MCAsmLayout &Layout,

View File

@ -68,12 +68,10 @@ public:
/// @name API
/// @{
virtual void RecordRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) = 0;
/// @}
@ -97,8 +95,14 @@ class MachObjectWriter : public MCObjectWriter {
/// @name Relocation Data
/// @{
llvm::DenseMap<const MCSectionData*,
std::vector<MachO::any_relocation_info> > Relocations;
struct RelAndSymbol {
const MCSymbolData *Sym;
MachO::any_relocation_info MRE;
RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE)
: Sym(Sym), MRE(MRE) {}
};
llvm::DenseMap<const MCSectionData *, std::vector<RelAndSymbol>> Relocations;
llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
/// @}
@ -213,9 +217,15 @@ public:
// - Input errors, where something cannot be correctly encoded. 'as' allows
// these through in many cases.
void addRelocation(const MCSectionData *SD,
// Add a relocation to be output in the object file. At the time this is
// called, the symbol indexes are not know, so if the relocation refers
// to a symbol it should be passed as \p RelSymbol so that it can be updated
// afterwards. If the relocation doesn't refer to a symbol, nullptr should be
// used.
void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD,
MachO::any_relocation_info &MRE) {
Relocations[SD].push_back(MRE);
RelAndSymbol P(RelSymbol, MRE);
Relocations[SD].push_back(P);
}
void RecordScatteredRelocation(const MCAssembler &Asm,
@ -231,7 +241,7 @@ public:
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue);
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;

View File

@ -76,12 +76,10 @@ public:
/// post layout binding. The implementation is responsible for storing
/// information about the relocation so that it can be emitted during
/// WriteObject().
virtual void RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
bool &IsPCRel,
uint64_t &FixedValue) = 0;
bool &IsPCRel, uint64_t &FixedValue) = 0;
/// \brief Check whether the difference (A - B) between two symbol
/// references is fully resolved.

View File

@ -219,7 +219,7 @@ class ELFObjectWriter : public MCObjectWriter {
const MCSymbolData *SD, uint64_t C,
unsigned Type) const;
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
@ -789,13 +789,11 @@ static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) {
return nullptr;
}
void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
bool &IsPCRel,
uint64_t &FixedValue) {
const MCFixup &Fixup, MCValue Target,
bool &IsPCRel, uint64_t &FixedValue) {
const MCSectionData *FixupSection = Fragment->getParent();
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

View File

@ -27,22 +27,7 @@ bool MCAsmInfoDarwin::isSectionAtomizableBySymbols(
// contain.
// Sections holding 2 byte strings require symbols in order to be atomized.
// There is no dedicated section for 4 byte strings.
if (SMO.getKind().isMergeable1ByteCString())
return false;
if (SMO.getSegmentName() == "__TEXT" &&
SMO.getSectionName() == "__objc_classname" &&
SMO.getType() == MachO::S_CSTRING_LITERALS)
return false;
if (SMO.getSegmentName() == "__TEXT" &&
SMO.getSectionName() == "__objc_methname" &&
SMO.getType() == MachO::S_CSTRING_LITERALS)
return false;
if (SMO.getSegmentName() == "__TEXT" &&
SMO.getSectionName() == "__objc_methtype" &&
SMO.getType() == MachO::S_CSTRING_LITERALS)
if (SMO.getType() == MachO::S_CSTRING_LITERALS)
return false;
if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring")

View File

@ -425,6 +425,16 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const {
return true;
}
void MCAssembler::addLocalUsedInReloc(const MCSymbol &Sym) {
assert(Sym.isTemporary());
LocalsUsedInReloc.insert(&Sym);
}
bool MCAssembler::isLocalUsedInReloc(const MCSymbol &Sym) const {
assert(Sym.isTemporary());
return LocalsUsedInReloc.count(&Sym);
}
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
// Non-temporary labels should always be visible to the linker.
if (!Symbol.isTemporary())
@ -434,8 +444,10 @@ bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
if (!Symbol.isInSection())
return false;
// Otherwise, check if the section requires symbols even for temporary labels.
return getBackend().doesSectionRequireSymbols(Symbol.getSection());
if (isLocalUsedInReloc(Symbol))
return true;
return false;
}
const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {

View File

@ -448,14 +448,11 @@ void MachObjectWriter::WriteLinkerOptionsLoadCommand(
assert(OS.tell() - Start == Size);
}
void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
void MachObjectWriter::RecordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
bool &IsPCRel,
uint64_t &FixedValue) {
const MCFixup &Fixup, MCValue Target,
bool &IsPCRel, uint64_t &FixedValue) {
TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup,
Target, FixedValue);
}
@ -616,6 +613,22 @@ void MachObjectWriter::ComputeSymbolTable(
ExternalSymbolData[i].SymbolData->setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
for (const MCSectionData &SD : Asm) {
std::vector<RelAndSymbol> &Relocs = Relocations[&SD];
for (RelAndSymbol &Rel : Relocs) {
if (!Rel.Sym)
continue;
// Set the Index and the IsExtern bit.
unsigned Index = Rel.Sym->getIndex();
assert(isInt<24>(Index));
if (IsLittleEndian)
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (-1 << 24)) | Index | (1 << 27);
else
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
}
}
}
void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
@ -662,10 +675,6 @@ void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
// Mark symbol difference expressions in variables (from .set or = directives)
// as absolute.
markAbsoluteVariableSymbols(Asm, Layout);
// Compute symbol table information and bind symbol indices.
ComputeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
UndefinedSymbolData);
}
bool MachObjectWriter::
@ -749,6 +758,10 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
void MachObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// Compute symbol table information and bind symbol indices.
ComputeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
UndefinedSymbolData);
unsigned NumSections = Asm.size();
const MCAssembler::VersionMinInfoType &VersionInfo =
Layout.getAssembler().getVersionMinInfo();
@ -839,7 +852,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
std::vector<RelAndSymbol> &Relocs = Relocations[it];
unsigned NumRelocs = Relocs.size();
uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
@ -933,10 +946,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
ie = Asm.end(); it != ie; ++it) {
// Write the section relocation entries, in reverse order to match 'as'
// (approximately, the exact algorithm is more complicated than this).
std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
std::vector<RelAndSymbol> &Relocs = Relocations[it];
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
Write32(Relocs[e - i - 1].r_word0);
Write32(Relocs[e - i - 1].r_word1);
Write32(Relocs[e - i - 1].MRE.r_word0);
Write32(Relocs[e - i - 1].MRE.r_word1);
}
}

View File

@ -175,7 +175,7 @@ public:
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
@ -661,13 +661,9 @@ bool WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
InSet, IsPCRel);
}
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
bool &IsPCRel,
uint64_t &FixedValue) {
void WinCOFFObjectWriter::RecordRelocation(
MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) {
assert(Target.getSymA() && "Relocation must reference a symbol!");
const MCSymbol &Symbol = Target.getSymA()->getSymbol();

View File

@ -317,42 +317,6 @@ public:
MachO::CPU_SUBTYPE_ARM64_ALL);
}
bool doesSectionRequireSymbols(const MCSection &Section) const override {
// Any section for which the linker breaks things into atoms needs to
// preserve symbols, including assembler local symbols, to identify
// those atoms. These sections are:
// Sections of type:
//
// S_CSTRING_LITERALS (e.g. __cstring)
// S_LITERAL_POINTERS (e.g. objc selector pointers)
// S_16BYTE_LITERALS, S_8BYTE_LITERALS, S_4BYTE_LITERALS
//
// Sections named:
//
// __TEXT,__eh_frame
// __TEXT,__ustring
// __DATA,__cfstring
// __DATA,__objc_classrefs
// __DATA,__objc_catlist
//
// FIXME: It would be better if the compiler used actual linker local
// symbols for each of these sections rather than preserving what
// are ostensibly assembler local symbols.
const MCSectionMachO &SMO = static_cast<const MCSectionMachO &>(Section);
return (SMO.getType() == MachO::S_CSTRING_LITERALS ||
SMO.getType() == MachO::S_4BYTE_LITERALS ||
SMO.getType() == MachO::S_8BYTE_LITERALS ||
SMO.getType() == MachO::S_16BYTE_LITERALS ||
SMO.getType() == MachO::S_LITERAL_POINTERS ||
(SMO.getSegmentName() == "__TEXT" &&
(SMO.getSectionName() == "__eh_frame" ||
SMO.getSectionName() == "__ustring")) ||
(SMO.getSegmentName() == "__DATA" &&
(SMO.getSectionName() == "__cfstring" ||
SMO.getSectionName() == "__objc_classrefs" ||
SMO.getSectionName() == "__objc_catlist")));
}
/// \brief Generate the compact unwind encoding from the CFI directives.
uint32_t generateCompactUnwindEncoding(
ArrayRef<MCCFIInstruction> Instrs) const override {

View File

@ -10,6 +10,7 @@
#include "MCTargetDesc/AArch64FixupKinds.h"
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@ -33,7 +34,7 @@ public:
: MCMachObjectTargetWriter(true /* is64Bit */, CPUType, CPUSubtype,
/*UseAggressiveSymbolFolding=*/true) {}
void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) override;
@ -112,8 +113,25 @@ bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
}
}
static bool canUseLocalRelocation(const MCSectionMachO &Section,
const MCSymbol &Symbol, unsigned Log2Size) {
// Debug info sections can use local relocations.
if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
return true;
// Otherwise, only pointer sized relocations are supported.
if (Log2Size != 3)
return false;
// But only if they don't point to a cstring.
if (!Symbol.isInSection())
return true;
const MCSectionMachO &RefSec = cast<MCSectionMachO>(Symbol.getSection());
return RefSec.getType() != MachO::S_CSTRING_LITERALS;
}
void AArch64MachObjectWriter::RecordRelocation(
MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) {
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
@ -123,9 +141,9 @@ void AArch64MachObjectWriter::RecordRelocation(
unsigned Log2Size = 0;
int64_t Value = 0;
unsigned Index = 0;
unsigned IsExtern = 0;
unsigned Type = 0;
unsigned Kind = Fixup.getKind();
const MCSymbolData *RelSymbol = nullptr;
FixupOffset += Fixup.getOffset();
@ -171,10 +189,8 @@ void AArch64MachObjectWriter::RecordRelocation(
// FIXME: Should this always be extern?
// SymbolNum of 0 indicates the absolute section.
Type = MachO::ARM64_RELOC_UNSIGNED;
Index = 0;
if (IsPCRel) {
IsExtern = 1;
Asm.getContext().FatalError(Fixup.getLoc(),
"PC relative absolute relocation!");
@ -198,15 +214,12 @@ void AArch64MachObjectWriter::RecordRelocation(
Layout.getSymbolOffset(&B_SD) ==
Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
// SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
Index = A_Base->getIndex();
IsExtern = 1;
Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
IsPCRel = 1;
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
(IsExtern << 27) | (Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
return;
} else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
@ -252,26 +265,31 @@ void AArch64MachObjectWriter::RecordRelocation(
? 0
: Writer->getSymbolAddress(B_Base, Layout));
Index = A_Base->getIndex();
IsExtern = 1;
Type = MachO::ARM64_RELOC_UNSIGNED;
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
(IsExtern << 27) | (Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
Index = B_Base->getIndex();
IsExtern = 1;
RelSymbol = B_Base;
Type = MachO::ARM64_RELOC_SUBTRACTOR;
} else { // A + constant
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
const MCSymbolData *Base = Asm.getAtom(&SD);
const MCSectionMachO &Section = static_cast<const MCSectionMachO &>(
Fragment->getParent()->getSection());
bool CanUseLocalRelocation =
canUseLocalRelocation(Section, *Symbol, Log2Size);
if (Symbol->isTemporary() && (Value || !CanUseLocalRelocation)) {
const MCSection &Sec = Symbol->getSection();
if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
Asm.addLocalUsedInReloc(*Symbol);
}
const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
const MCSymbolData *Base = Asm.getAtom(&SD);
// If the symbol is a variable and we weren't able to get a Base for it
// (i.e., it's not in the symbol table associated with a section) resolve
// the relocation based its expansion instead.
@ -310,16 +328,13 @@ void AArch64MachObjectWriter::RecordRelocation(
// sections, and for pointer-sized relocations (.quad), we allow section
// relocations. It's code sections that run into trouble.
if (Base) {
Index = Base->getIndex();
IsExtern = 1;
RelSymbol = Base;
// Add the local offset, if needed.
if (Base != &SD)
Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
} else if (Symbol->isInSection()) {
// Pointer-sized relocations can use a local relocation. Otherwise,
// we have to be in a debug info section.
if (!Section.hasAttribute(MachO::S_ATTR_DEBUG) && Log2Size != 3)
if (!CanUseLocalRelocation)
Asm.getContext().FatalError(
Fixup.getLoc(),
"unsupported relocation of local symbol '" + Symbol->getName() +
@ -329,7 +344,6 @@ void AArch64MachObjectWriter::RecordRelocation(
const MCSectionData &SymSD =
Asm.getSectionData(SD.getSymbol().getSection());
Index = SymSD.getOrdinal() + 1;
IsExtern = 0;
Value += Writer->getSymbolAddress(&SD, Layout);
if (IsPCRel)
@ -362,16 +376,16 @@ void AArch64MachObjectWriter::RecordRelocation(
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
(IsExtern << 27) | (Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 =
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
// Now set up the Addend relocation.
Type = MachO::ARM64_RELOC_ADDEND;
Index = Value;
RelSymbol = nullptr;
IsPCRel = 0;
Log2Size = 2;
IsExtern = 0;
// Put zero into the instruction itself. The addend is in the relocation.
Value = 0;
@ -383,9 +397,9 @@ void AArch64MachObjectWriter::RecordRelocation(
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
(IsExtern << 27) | (Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 =
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
MCObjectWriter *llvm::createAArch64MachObjectWriter(raw_ostream &OS,

View File

@ -54,10 +54,10 @@ public:
: MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
/*UseAggressiveSymbolFolding=*/true) {}
void RecordRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) override;
void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) override;
};
}
@ -232,7 +232,7 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value2;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
}
MachO::any_relocation_info MRE;
@ -243,7 +243,7 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
}
void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
@ -297,7 +297,7 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value2;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
}
MachO::any_relocation_info MRE;
@ -307,7 +307,7 @@ void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
}
bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
@ -351,11 +351,10 @@ bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
}
void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) {
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
unsigned Log2Size;
@ -401,8 +400,8 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
// See <reloc.h>.
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
unsigned Index = 0;
unsigned IsExtern = 0;
unsigned Type = 0;
const MCSymbolData *RelSymbol = nullptr;
if (Target.isAbsolute()) { // constant
// FIXME!
@ -422,8 +421,7 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
// Check whether we need an external or internal relocation.
if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, SD,
FixedValue)) {
IsExtern = 1;
Index = SD->getIndex();
RelSymbol = SD;
// For external relocations, make sure to offset the fixup value to
// compensate for the addend of the symbol address, if it was
@ -447,11 +445,8 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) |
(IsPCRel << 24) |
(Log2Size << 25) |
(IsExtern << 27) |
(Type << 28));
MRE.r_word1 =
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
// Even when it's not a scattered relocation, movw/movt always uses
// a PAIR relocation.
@ -476,10 +471,10 @@ void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
(Log2Size << 25) |
(MachO::ARM_RELOC_PAIR << 28));
Writer->addRelocation(Fragment->getParent(), MREPair);
Writer->addRelocation(nullptr, Fragment->getParent(), MREPair);
}
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,

View File

@ -41,7 +41,7 @@ public:
: MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
/*UseAggressiveSymbolFolding=*/Is64Bit) {}
void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) override {
@ -282,7 +282,7 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
MachO::any_relocation_info MRE;
makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
Log2Size, IsPCRel, Value2);
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
} else {
// If the offset is more than 24-bits, it won't fit in a scattered
// relocation offset field, so we fall back to using a non-scattered
@ -296,7 +296,7 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
}
MachO::any_relocation_info MRE;
makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value);
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
return true;
}
@ -331,9 +331,9 @@ void PPCMachObjectWriter::RecordPPCRelocation(
// See <reloc.h>.
const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
unsigned Index = 0;
unsigned IsExtern = 0;
unsigned Type = RelocType;
const MCSymbolData *RelSymbol = nullptr;
if (Target.isAbsolute()) { // constant
// SymbolNum of 0 indicates the absolute section.
//
@ -355,8 +355,7 @@ void PPCMachObjectWriter::RecordPPCRelocation(
// Check whether we need an external or internal relocation.
if (Writer->doesSymbolRequireExternRelocation(SD)) {
IsExtern = 1;
Index = SD->getIndex();
RelSymbol = SD;
// For external relocations, make sure to offset the fixup value to
// compensate for the addend of the symbol address, if it was
// undefined. This occurs with weak definitions, for example.
@ -375,9 +374,8 @@ void PPCMachObjectWriter::RecordPPCRelocation(
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, IsExtern,
Type);
Writer->addRelocation(Fragment->getParent(), MRE);
makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, false, Type);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
MCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit,

View File

@ -29,7 +29,7 @@ public:
const MCAsmLayout &Layout) override {
//XXX: Implement if necessary.
}
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override {

View File

@ -777,19 +777,6 @@ public:
MachO::CPU_TYPE_X86_64, Subtype);
}
bool doesSectionRequireSymbols(const MCSection &Section) const override {
// Temporary labels in the string literals sections require symbols. The
// issue is that the x86_64 relocation format does not allow symbol +
// offset, and so the linker does not have enough information to resolve the
// access to the appropriate atom unless an external relocation is used. For
// non-cstring sections, we expect the compiler to use a non-temporary label
// for anything that could have an addend pointing outside the symbol.
//
// See <rdar://problem/4765733>.
const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
return SMO.getType() == MachO::S_CSTRING_LITERALS;
}
/// \brief Generate the compact unwind encoding for the CFI instructions.
uint32_t generateCompactUnwindEncoding(
ArrayRef<MCCFIInstruction> Instrs) const override {

View File

@ -10,6 +10,7 @@
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "MCTargetDesc/X86FixupKinds.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@ -47,23 +48,21 @@ class X86MachObjectWriter : public MCMachObjectTargetWriter {
const MCFixup &Fixup,
MCValue Target,
uint64_t &FixedValue);
void RecordX86_64Relocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
void RecordX86_64Relocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
uint64_t &FixedValue);
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue);
public:
X86MachObjectWriter(bool Is64Bit, uint32_t CPUType,
uint32_t CPUSubtype)
: MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
/*UseAggressiveSymbolFolding=*/Is64Bit) {}
void RecordRelocation(MachObjectWriter *Writer,
const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) override {
void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) override {
if (Writer->is64Bit())
RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
FixedValue);
@ -97,13 +96,10 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
}
}
void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
uint64_t &FixedValue) {
void X86MachObjectWriter::RecordX86_64Relocation(
MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) {
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
@ -117,6 +113,7 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
unsigned Index = 0;
unsigned IsExtern = 0;
unsigned Type = 0;
const MCSymbolData *RelSymbol = nullptr;
Value = Target.getConstant();
@ -132,7 +129,6 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
if (Target.isAbsolute()) { // constant
// SymbolNum of 0 indicates the absolute section.
Type = MachO::X86_64_RELOC_UNSIGNED;
Index = 0;
// FIXME: I believe this is broken, I don't think the linker can understand
// it. I think it would require a local relocation, but I'm not sure if that
@ -193,36 +189,30 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
Value -= Writer->getSymbolAddress(&B_SD, Layout) -
(!B_Base ? 0 : Writer->getSymbolAddress(B_Base, Layout));
if (A_Base) {
Index = A_Base->getIndex();
IsExtern = 1;
} else {
if (!A_Base)
Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
IsExtern = 0;
}
Type = MachO::X86_64_RELOC_UNSIGNED;
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) |
(IsPCRel << 24) |
(Log2Size << 25) |
(IsExtern << 27) |
(Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 =
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
if (B_Base) {
Index = B_Base->getIndex();
IsExtern = 1;
} else {
if (B_Base)
RelSymbol = B_Base;
else
Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
IsExtern = 0;
}
Type = MachO::X86_64_RELOC_SUBTRACTOR;
} else {
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
if (Symbol->isTemporary() && Value) {
const MCSection &Sec = Symbol->getSection();
if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
Asm.addLocalUsedInReloc(*Symbol);
}
const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
const MCSymbolData *Base = Asm.getAtom(&SD);
RelSymbol = Asm.getAtom(&SD);
// Relocations inside debug sections always use local relocations when
// possible. This seems to be done because the debugger doesn't fully
@ -232,23 +222,20 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
Fragment->getParent()->getSection());
if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
Base = nullptr;
RelSymbol = nullptr;
}
// x86_64 almost always uses external relocations, except when there is no
// symbol to use as a base address (a local symbol with no preceding
// non-local symbol).
if (Base) {
Index = Base->getIndex();
IsExtern = 1;
if (RelSymbol) {
// Add the local offset, if needed.
if (Base != &SD)
Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
if (RelSymbol != &SD)
Value +=
Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(RelSymbol);
} else if (Symbol->isInSection() && !Symbol->isVariable()) {
// The index is the section ordinal (1-based).
Index = SD.getFragment()->getParent()->getOrdinal() + 1;
IsExtern = 0;
Value += Writer->getSymbolAddress(&SD, Layout);
if (IsPCRel)
@ -347,12 +334,9 @@ void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) |
(IsPCRel << 24) |
(Log2Size << 25) |
(IsExtern << 27) |
(Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
(IsExtern << 27) | (Type << 28);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
@ -424,7 +408,7 @@ bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value2;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
} else {
// If the offset is more than 24-bits, it won't fit in a scattered
// relocation offset field, so we fall back to using a non-scattered
@ -446,7 +430,7 @@ bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
(IsPCRel << 30) |
MachO::R_SCATTERED);
MRE.r_word1 = Value;
Writer->addRelocation(Fragment->getParent(), MRE);
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
return true;
}
@ -467,7 +451,6 @@ void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
// Get the symbol data.
const MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
unsigned Index = SD_A->getIndex();
// We're only going to have a second symbol in pic mode and it'll be a
// subtraction from the picbase. For 32-bit pic the addend is the difference
@ -490,12 +473,9 @@ void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
MRE.r_word0 = Value;
MRE.r_word1 = ((Index << 0) |
(IsPCRel << 24) |
(Log2Size << 25) |
(1 << 27) | // r_extern
(MachO::GENERIC_RELOC_TLV << 28)); // r_type
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 =
(IsPCRel << 24) | (Log2Size << 25) | (MachO::GENERIC_RELOC_TLV << 28);
Writer->addRelocation(SD_A, Fragment->getParent(), MRE);
}
void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
@ -546,8 +526,8 @@ void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
// See <reloc.h>.
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
unsigned Index = 0;
unsigned IsExtern = 0;
unsigned Type = 0;
const MCSymbolData *RelSymbol = nullptr;
if (Target.isAbsolute()) { // constant
// SymbolNum of 0 indicates the absolute section.
@ -568,8 +548,7 @@ void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
// Check whether we need an external or internal relocation.
if (Writer->doesSymbolRequireExternRelocation(SD)) {
IsExtern = 1;
Index = SD->getIndex();
RelSymbol = SD;
// For external relocations, make sure to offset the fixup value to
// compensate for the addend of the symbol address, if it was
// undefined. This occurs with weak definitions, for example.
@ -591,12 +570,9 @@ void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
// struct relocation_info (8 bytes)
MachO::any_relocation_info MRE;
MRE.r_word0 = FixupOffset;
MRE.r_word1 = ((Index << 0) |
(IsPCRel << 24) |
(Log2Size << 25) |
(IsExtern << 27) |
(Type << 28));
Writer->addRelocation(Fragment->getParent(), MRE);
MRE.r_word1 =
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS,

View File

@ -0,0 +1,59 @@
// RUN: llvm-mc -triple aarch64-apple-darwin14 %s -filetype=obj -o - | llvm-readobj -r --expand-relocs | FileCheck %s
// Test that we "S + K" produce a relocation with a symbol, but just S produces
// a relocation with the section.
.section __TEXT,__literal4,4byte_literals
L0:
.long 42
.section __TEXT,__cstring,cstring_literals
L1:
.asciz "42"
.section __DATA,__data
.quad L0
.quad L0 + 1
.quad L1
.quad L1 + 1
// CHECK: Relocations [
// CHECK-NEXT: Section __data {
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x18
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 1
// CHECK-NEXT: Type: ARM64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: L1
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x10
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 1
// CHECK-NEXT: Type: ARM64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: L1
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x8
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 1
// CHECK-NEXT: Type: ARM64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: L0
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x0
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 0
// CHECK-NEXT: Type: ARM64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: 0x2
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]

View File

@ -0,0 +1,59 @@
// RUN: llvm-mc -triple x86_64-apple-darwin14 %s -filetype=obj -o - | llvm-readobj -r --expand-relocs | FileCheck %s
// Test that we "S + K" produce a relocation with a symbol, but just S produces
// a relocation with the section.
.section __TEXT,__literal4,4byte_literals
L0:
.long 42
.section __TEXT,__cstring,cstring_literals
L1:
.asciz "42"
.section __DATA,__data
.quad L0
.quad L0 + 1
.quad L1
.quad L1 + 1
// CHECK: Relocations [
// CHECK-NEXT: Section __data {
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x18
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 1
// CHECK-NEXT: Type: X86_64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: L1
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x10
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 0
// CHECK-NEXT: Type: X86_64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: 0x3
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x8
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 1
// CHECK-NEXT: Type: X86_64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: L0
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x0
// CHECK-NEXT: PCRel: 0
// CHECK-NEXT: Length: 3
// CHECK-NEXT: Extern: 0
// CHECK-NEXT: Type: X86_64_RELOC_UNSIGNED (0)
// CHECK-NEXT: Symbol: 0x2
// CHECK-NEXT: Scattered: 0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]

View File

@ -121,6 +121,12 @@ D38:
//L39:
//D39:
.section foo, bar
.long L4 + 1
.long L35 + 1
.long L36 + 1
.long L37 + 1
.long L38 + 1
// CHECK: Symbols [
// CHECK-NEXT: Symbol {