mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Move class methods out-of-line. This reduces the indentation, and is more in
line with LLVM's general coding style. No functionality change. llvm-svn: 133645
This commit is contained in:
parent
5640b59656
commit
19f2f807eb
@ -120,6 +120,153 @@ private:
|
||||
return SectionAddress.lookup(SD);
|
||||
}
|
||||
uint64_t getSymbolAddress(const MCSymbolData* SD,
|
||||
const MCAsmLayout &Layout) const;
|
||||
|
||||
uint64_t getFragmentAddress(const MCFragment *Fragment,
|
||||
const MCAsmLayout &Layout) const {
|
||||
return getSectionAddress(Fragment->getParent()) +
|
||||
Layout.getFragmentOffset(Fragment);
|
||||
}
|
||||
|
||||
uint64_t getPaddingSize(const MCSectionData *SD,
|
||||
const MCAsmLayout &Layout) const;
|
||||
public:
|
||||
MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
|
||||
bool _IsLittleEndian)
|
||||
: MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
|
||||
}
|
||||
|
||||
/// @name Target Writer Proxy Accessors
|
||||
/// @{
|
||||
|
||||
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
||||
bool isARM() const {
|
||||
uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask;
|
||||
return CPUType == mach::CTM_ARM;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
bool SubsectionsViaSymbols);
|
||||
|
||||
/// WriteSegmentLoadCommand - Write a segment load command.
|
||||
///
|
||||
/// \arg NumSections - The number of sections in this segment.
|
||||
/// \arg SectionDataSize - The total size of the sections.
|
||||
void WriteSegmentLoadCommand(unsigned NumSections,
|
||||
uint64_t VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
uint64_t SectionDataSize);
|
||||
|
||||
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCSectionData &SD, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations);
|
||||
|
||||
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
||||
uint32_t StringTableOffset,
|
||||
uint32_t StringTableSize);
|
||||
|
||||
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
|
||||
uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol,
|
||||
uint32_t NumExternalSymbols,
|
||||
uint32_t FirstUndefinedSymbol,
|
||||
uint32_t NumUndefinedSymbols,
|
||||
uint32_t IndirectSymbolOffset,
|
||||
uint32_t NumIndirectSymbols);
|
||||
|
||||
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
|
||||
|
||||
// FIXME: We really need to improve the relocation validation. Basically, we
|
||||
// want to implement a separate computation which evaluates the relocation
|
||||
// entry as the linker would, and verifies that the resultant fixup value is
|
||||
// exactly what the encoder wanted. This will catch several classes of
|
||||
// problems:
|
||||
//
|
||||
// - Relocation entry bugs, the two algorithms are unlikely to have the same
|
||||
// exact bug.
|
||||
//
|
||||
// - Relaxation issues, where we forget to relax something.
|
||||
//
|
||||
// - Input errors, where something cannot be correctly encoded. 'as' allows
|
||||
// these through in many cases.
|
||||
|
||||
static bool isFixupKindRIPRel(unsigned Kind) {
|
||||
return Kind == X86::reloc_riprel_4byte ||
|
||||
Kind == X86::reloc_riprel_4byte_movq_load;
|
||||
}
|
||||
void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
void RecordScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
void RecordARMScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
void RecordARMMovwMovtRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
void RecordTLVPRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
|
||||
unsigned &Log2Size);
|
||||
|
||||
void RecordARMRelocation(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, uint64_t &FixedValue);
|
||||
|
||||
void BindIndirectSymbols(MCAssembler &Asm);
|
||||
|
||||
/// ComputeSymbolTable - Compute the symbol table data
|
||||
///
|
||||
/// \param StringTable [out] - The string table data.
|
||||
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
||||
/// string table.
|
||||
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
||||
std::vector<MachSymbolData> &LocalSymbolData,
|
||||
std::vector<MachSymbolData> &ExternalSymbolData,
|
||||
std::vector<MachSymbolData> &UndefinedSymbolData);
|
||||
|
||||
void computeSectionAddresses(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout);
|
||||
|
||||
void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||
|
||||
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbolData &DataA,
|
||||
const MCFragment &FB,
|
||||
bool InSet,
|
||||
bool IsPCRel) const;
|
||||
|
||||
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData* SD,
|
||||
const MCAsmLayout &Layout) const {
|
||||
const MCSymbol &S = SD->getSymbol();
|
||||
|
||||
@ -150,14 +297,9 @@ private:
|
||||
|
||||
return getSectionAddress(SD->getFragment()->getParent()) +
|
||||
Layout.getSymbolOffset(SD);
|
||||
}
|
||||
uint64_t getFragmentAddress(const MCFragment *Fragment,
|
||||
const MCAsmLayout &Layout) const {
|
||||
return getSectionAddress(Fragment->getParent()) +
|
||||
Layout.getFragmentOffset(Fragment);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t getPaddingSize(const MCSectionData *SD,
|
||||
uint64_t MachObjectWriter::getPaddingSize(const MCSectionData *SD,
|
||||
const MCAsmLayout &Layout) const {
|
||||
uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
|
||||
unsigned Next = SD->getLayoutOrder() + 1;
|
||||
@ -168,26 +310,10 @@ private:
|
||||
if (NextSD.getSection().isVirtualSection())
|
||||
return 0;
|
||||
return OffsetToAlignment(EndAddr, NextSD.getAlignment());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
|
||||
bool _IsLittleEndian)
|
||||
: MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
|
||||
}
|
||||
|
||||
/// @name Target Writer Proxy Accessors
|
||||
/// @{
|
||||
|
||||
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
||||
bool isARM() const {
|
||||
uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask;
|
||||
return CPUType == mach::CTM_ARM;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
void MachObjectWriter::WriteHeader(unsigned NumLoadCommands,
|
||||
unsigned LoadCommandsSize,
|
||||
bool SubsectionsViaSymbols) {
|
||||
uint32_t Flags = 0;
|
||||
|
||||
@ -214,13 +340,13 @@ public:
|
||||
|
||||
assert(OS.tell() - Start ==
|
||||
(is64Bit() ? macho::Header64Size : macho::Header32Size));
|
||||
}
|
||||
}
|
||||
|
||||
/// WriteSegmentLoadCommand - Write a segment load command.
|
||||
///
|
||||
/// \arg NumSections - The number of sections in this segment.
|
||||
/// \arg SectionDataSize - The total size of the sections.
|
||||
void WriteSegmentLoadCommand(unsigned NumSections,
|
||||
/// WriteSegmentLoadCommand - Write a segment load command.
|
||||
///
|
||||
/// \arg NumSections - The number of sections in this segment.
|
||||
/// \arg SectionDataSize - The total size of the sections.
|
||||
void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections,
|
||||
uint64_t VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
uint64_t SectionDataSize) {
|
||||
@ -256,11 +382,14 @@ public:
|
||||
Write32(0); // flags
|
||||
|
||||
assert(OS.tell() - Start == SegmentLoadCommandSize);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCSectionData &SD, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations) {
|
||||
void MachObjectWriter::WriteSection(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCSectionData &SD,
|
||||
uint64_t FileOffset,
|
||||
uint64_t RelocationsStart,
|
||||
unsigned NumRelocations) {
|
||||
uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
|
||||
|
||||
// The offset is unused for virtual sections.
|
||||
@ -303,9 +432,10 @@ public:
|
||||
|
||||
assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size :
|
||||
macho::Section32Size));
|
||||
}
|
||||
}
|
||||
|
||||
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
||||
void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset,
|
||||
uint32_t NumSymbols,
|
||||
uint32_t StringTableOffset,
|
||||
uint32_t StringTableSize) {
|
||||
// struct symtab_command (24 bytes)
|
||||
@ -321,9 +451,9 @@ public:
|
||||
Write32(StringTableSize);
|
||||
|
||||
assert(OS.tell() - Start == macho::SymtabLoadCommandSize);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
|
||||
void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
|
||||
uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol,
|
||||
uint32_t NumExternalSymbols,
|
||||
@ -358,9 +488,9 @@ public:
|
||||
Write32(0); // nlocrel
|
||||
|
||||
assert(OS.tell() - Start == macho::DysymtabLoadCommandSize);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) {
|
||||
void MachObjectWriter::WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) {
|
||||
MCSymbolData &Data = *MSD.SymbolData;
|
||||
const MCSymbol &Symbol = Data.getSymbol();
|
||||
uint8_t Type = 0;
|
||||
@ -423,29 +553,13 @@ public:
|
||||
Write64(Address);
|
||||
else
|
||||
Write32(Address);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: We really need to improve the relocation validation. Basically, we
|
||||
// want to implement a separate computation which evaluates the relocation
|
||||
// entry as the linker would, and verifies that the resultant fixup value is
|
||||
// exactly what the encoder wanted. This will catch several classes of
|
||||
// problems:
|
||||
//
|
||||
// - Relocation entry bugs, the two algorithms are unlikely to have the same
|
||||
// exact bug.
|
||||
//
|
||||
// - Relaxation issues, where we forget to relax something.
|
||||
//
|
||||
// - Input errors, where something cannot be correctly encoded. 'as' allows
|
||||
// these through in many cases.
|
||||
|
||||
static bool isFixupKindRIPRel(unsigned Kind) {
|
||||
return Kind == X86::reloc_riprel_4byte ||
|
||||
Kind == X86::reloc_riprel_4byte_movq_load;
|
||||
}
|
||||
void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
void MachObjectWriter::RecordX86_64Relocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
|
||||
@ -464,11 +578,11 @@ public:
|
||||
Value = Target.getConstant();
|
||||
|
||||
if (IsPCRel) {
|
||||
// Compensate for the relocation offset, Darwin x86_64 relocations only
|
||||
// have the addend and appear to have attempted to define it to be the
|
||||
// actual expression addend without the PCrel bias. However, instructions
|
||||
// with data following the relocation are not accommodated for (see comment
|
||||
// below regarding SIGNED{1,2,4}), so it isn't exactly that either.
|
||||
// Compensate for the relocation offset, Darwin x86_64 relocations only have
|
||||
// the addend and appear to have attempted to define it to be the actual
|
||||
// expression addend without the PCrel bias. However, instructions with data
|
||||
// following the relocation are not accommodated for (see comment below
|
||||
// regarding SIGNED{1,2,4}), so it isn't exactly that either.
|
||||
Value += 1LL << Log2Size;
|
||||
}
|
||||
|
||||
@ -477,11 +591,10 @@ public:
|
||||
Type = macho::RIT_X86_64_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 would work either. The official way to get an absolute
|
||||
// PCrel relocation is to use an absolute symbol (which we don't support
|
||||
// yet).
|
||||
// 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
|
||||
// would work either. The official way to get an absolute PCrel relocation
|
||||
// is to use an absolute symbol (which we don't support yet).
|
||||
if (IsPCRel) {
|
||||
IsExtern = 1;
|
||||
Type = macho::RIT_X86_64_Branch;
|
||||
@ -507,14 +620,14 @@ public:
|
||||
|
||||
// The support for the situation where one or both of the symbols would
|
||||
// require a local relocation is handled just like if the symbols were
|
||||
// external. This is certainly used in the case of debug sections where
|
||||
// the section has only temporary symbols and thus the symbols don't have
|
||||
// base symbols. This is encoded using the section ordinal and
|
||||
// non-extern relocation entries.
|
||||
// external. This is certainly used in the case of debug sections where the
|
||||
// section has only temporary symbols and thus the symbols don't have base
|
||||
// symbols. This is encoded using the section ordinal and non-extern
|
||||
// relocation entries.
|
||||
|
||||
// Darwin 'as' doesn't emit correct relocations for this (it ends up with
|
||||
// a single SIGNED relocation); reject it for now. Except the case where
|
||||
// both symbols don't have a base, equal but both NULL.
|
||||
// Darwin 'as' doesn't emit correct relocations for this (it ends up with a
|
||||
// single SIGNED relocation); reject it for now. Except the case where both
|
||||
// symbols don't have a base, equal but both NULL.
|
||||
if (A_Base == B_Base && A_Base)
|
||||
report_fatal_error("unsupported relocation with identical base");
|
||||
|
||||
@ -624,15 +737,15 @@ public:
|
||||
// containing L<foo>. Generally, this shouldn't occur but it does
|
||||
// happen when we have a RIPrel instruction with data following the
|
||||
// relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
|
||||
// adjustment Darwin x86_64 uses, the offset is still negative and
|
||||
// the linker has no way to recognize this.
|
||||
// adjustment Darwin x86_64 uses, the offset is still negative and the
|
||||
// linker has no way to recognize this.
|
||||
//
|
||||
// To work around this, Darwin uses several special relocation types
|
||||
// to indicate the offsets. However, the specification or
|
||||
// implementation of these seems to also be incomplete; they should
|
||||
// adjust the addend as well based on the actual encoded instruction
|
||||
// (the additional bias), but instead appear to just look at the
|
||||
// final offset.
|
||||
// (the additional bias), but instead appear to just look at the final
|
||||
// offset.
|
||||
switch (-(Target.getConstant() + (1LL << Log2Size))) {
|
||||
case 1: Type = macho::RIT_X86_64_Signed1; break;
|
||||
case 2: Type = macho::RIT_X86_64_Signed2; break;
|
||||
@ -650,10 +763,10 @@ public:
|
||||
if (Modifier == MCSymbolRefExpr::VK_GOT) {
|
||||
Type = macho::RIT_X86_64_GOT;
|
||||
} else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
|
||||
// GOTPCREL is allowed as a modifier on non-PCrel instructions, in
|
||||
// which case all we do is set the PCrel bit in the relocation entry;
|
||||
// this is used with exception handling, for example. The source is
|
||||
// required to include any necessary offset directly.
|
||||
// GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
|
||||
// case all we do is set the PCrel bit in the relocation entry; this is
|
||||
// used with exception handling, for example. The source is required to
|
||||
// include any necessary offset directly.
|
||||
Type = macho::RIT_X86_64_GOT;
|
||||
IsPCRel = 1;
|
||||
} else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
|
||||
@ -677,12 +790,13 @@ public:
|
||||
(IsExtern << 27) |
|
||||
(Type << 28));
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordScatteredRelocation(const MCAssembler &Asm,
|
||||
void MachObjectWriter::RecordScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
@ -712,8 +826,8 @@ public:
|
||||
// Select the appropriate difference relocation type.
|
||||
//
|
||||
// Note that there is no longer any semantic difference between these two
|
||||
// relocation types from the linkers point of view, this is done solely
|
||||
// for pedantic compatibility with 'as'.
|
||||
// relocation types from the linkers point of view, this is done solely for
|
||||
// pedantic compatibility with 'as'.
|
||||
Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
|
||||
(unsigned)macho::RIT_Generic_LocalDifference;
|
||||
Value2 = getSymbolAddress(B_SD, Layout);
|
||||
@ -741,12 +855,13 @@ public:
|
||||
macho::RF_Scattered);
|
||||
MRE.Word1 = Value;
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordARMScatteredRelocation(const MCAssembler &Asm,
|
||||
void MachObjectWriter::RecordARMScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
@ -800,12 +915,13 @@ public:
|
||||
macho::RF_Scattered);
|
||||
MRE.Word1 = Value;
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordARMMovwMovtRelocation(const MCAssembler &Asm,
|
||||
void MachObjectWriter::RecordARMMovwMovtRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
@ -840,9 +956,9 @@ public:
|
||||
// Relocations are written out in reverse order, so the PAIR comes first.
|
||||
// ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
|
||||
//
|
||||
// For these two r_type relocations they always have a pair following them
|
||||
// and the r_length bits are used differently. The encoding of the
|
||||
// r_length is as follows:
|
||||
// For these two r_type relocations they always have a pair following them and
|
||||
// the r_length bits are used differently. The encoding of the r_length is as
|
||||
// follows:
|
||||
// low bit of r_length:
|
||||
// 0 - :lower16: for movw instructions
|
||||
// 1 - :upper16: for movt instructions
|
||||
@ -894,12 +1010,13 @@ public:
|
||||
macho::RF_Scattered);
|
||||
MRE.Word1 = Value;
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordTLVPRelocation(const MCAssembler &Asm,
|
||||
void MachObjectWriter::RecordTLVPRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
|
||||
!is64Bit() &&
|
||||
@ -915,8 +1032,8 @@ public:
|
||||
|
||||
// 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
|
||||
// between the picbase and the next address. For 32-bit static the addend
|
||||
// is zero.
|
||||
// between the picbase and the next address. For 32-bit static the addend is
|
||||
// zero.
|
||||
if (Target.getSymB()) {
|
||||
// If this is a subtraction then we're pcrel.
|
||||
uint32_t FixupAddress =
|
||||
@ -939,9 +1056,9 @@ public:
|
||||
(1 << 27) | // Extern
|
||||
(macho::RIT_Generic_TLV << 28)); // Type
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
|
||||
bool MachObjectWriter::getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
|
||||
unsigned &Log2Size) {
|
||||
RelocType = unsigned(macho::RIT_Vanilla);
|
||||
Log2Size = ~0U;
|
||||
@ -1004,10 +1121,13 @@ public:
|
||||
Log2Size = llvm::Log2_32(4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, uint64_t &FixedValue) {
|
||||
}
|
||||
void MachObjectWriter::RecordARMRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
unsigned Log2Size;
|
||||
unsigned RelocType = macho::RIT_Vanilla;
|
||||
@ -1016,8 +1136,8 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a difference or a defined symbol plus an offset, then we need
|
||||
// a scattered relocation entry. Differences always require scattered
|
||||
// If this is a difference or a defined symbol plus an offset, then we need a
|
||||
// scattered relocation entry. Differences always require scattered
|
||||
// relocations.
|
||||
if (Target.getSymB()) {
|
||||
if (RelocType == macho::RIT_ARM_Half ||
|
||||
@ -1034,8 +1154,8 @@ public:
|
||||
SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
|
||||
|
||||
// FIXME: For other platforms, we need to use scattered relocations for
|
||||
// internal relocations with offsets. If this is an internal relocation
|
||||
// with an offset, it also needs a scattered relocation entry.
|
||||
// internal relocations with offsets. If this is an internal relocation with
|
||||
// an offset, it also needs a scattered relocation entry.
|
||||
//
|
||||
// Is this right for ARM?
|
||||
uint32_t Offset = Target.getConstant();
|
||||
@ -1070,6 +1190,7 @@ public:
|
||||
if (doesSymbolRequireExternRelocation(SD)) {
|
||||
IsExtern = 1;
|
||||
Index = SD->getIndex();
|
||||
|
||||
// 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.
|
||||
@ -1098,11 +1219,14 @@ public:
|
||||
(IsExtern << 27) |
|
||||
(Type << 28));
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, uint64_t &FixedValue) {
|
||||
void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
// FIXME: These needs to be factored into the target Mach-O writer.
|
||||
if (isARM()) {
|
||||
RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
|
||||
@ -1123,9 +1247,9 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a difference or a defined symbol plus an offset, then we need
|
||||
// a scattered relocation entry.
|
||||
// Differences always require scattered relocations.
|
||||
// If this is a difference or a defined symbol plus an offset, then we need a
|
||||
// scattered relocation entry. Differences always require scattered
|
||||
// relocations.
|
||||
if (Target.getSymB())
|
||||
return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
||||
Target, Log2Size, FixedValue);
|
||||
@ -1135,8 +1259,8 @@ public:
|
||||
if (Target.getSymA())
|
||||
SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
|
||||
|
||||
// If this is an internal relocation with an offset, it also needs a
|
||||
// scattered relocation entry.
|
||||
// If this is an internal relocation with an offset, it also needs a scattered
|
||||
// relocation entry.
|
||||
uint32_t Offset = Target.getConstant();
|
||||
if (IsPCRel)
|
||||
Offset += 1 << Log2Size;
|
||||
@ -1198,13 +1322,13 @@ public:
|
||||
(IsExtern << 27) |
|
||||
(Type << 28));
|
||||
Relocations[Fragment->getParent()].push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void BindIndirectSymbols(MCAssembler &Asm) {
|
||||
void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) {
|
||||
// This is the point where 'as' creates actual symbols for indirect symbols
|
||||
// (in the following two passes). It would be easier for us to do this
|
||||
// sooner when we see the attribute, but that makes getting the order in the
|
||||
// symbol table much more complicated than it is worth.
|
||||
// (in the following two passes). It would be easier for us to do this sooner
|
||||
// when we see the attribute, but that makes getting the order in the symbol
|
||||
// table much more complicated than it is worth.
|
||||
//
|
||||
// FIXME: Revisit this when the dust settles.
|
||||
|
||||
@ -1248,14 +1372,14 @@ public:
|
||||
if (Created)
|
||||
Entry.setFlags(Entry.getFlags() | 0x0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ComputeSymbolTable - Compute the symbol table data
|
||||
///
|
||||
/// \param StringTable [out] - The string table data.
|
||||
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
||||
/// string table.
|
||||
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
||||
/// ComputeSymbolTable - Compute the symbol table data
|
||||
///
|
||||
/// \param StringTable [out] - The string table data.
|
||||
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
||||
/// string table.
|
||||
void MachObjectWriter::ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
||||
std::vector<MachSymbolData> &LocalSymbolData,
|
||||
std::vector<MachSymbolData> &ExternalSymbolData,
|
||||
std::vector<MachSymbolData> &UndefinedSymbolData) {
|
||||
@ -1362,9 +1486,9 @@ public:
|
||||
// The string table is padded to a multiple of 4.
|
||||
while (StringTable.size() % 4)
|
||||
StringTable += '\x00';
|
||||
}
|
||||
}
|
||||
|
||||
void computeSectionAddresses(const MCAssembler &Asm,
|
||||
void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
uint64_t StartAddress = 0;
|
||||
const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
|
||||
@ -1373,14 +1497,15 @@ public:
|
||||
StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
|
||||
SectionAddress[SD] = StartAddress;
|
||||
StartAddress += Layout.getSectionAddressSize(SD);
|
||||
|
||||
// Explicitly pad the section to match the alignment requirements of the
|
||||
// following one. This is for 'gas' compatibility, it shouldn't
|
||||
/// strictly be necessary.
|
||||
StartAddress += getPaddingSize(SD, Layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
|
||||
void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
|
||||
computeSectionAddresses(Asm, Layout);
|
||||
|
||||
// Create symbol data for any indirect symbols.
|
||||
@ -1389,9 +1514,9 @@ public:
|
||||
// Compute symbol table information and bind symbol indices.
|
||||
ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
|
||||
UndefinedSymbolData);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
bool MachObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbolData &DataA,
|
||||
const MCFragment &FB,
|
||||
bool InSet,
|
||||
@ -1413,13 +1538,12 @@ public:
|
||||
if (IsPCRel) {
|
||||
// The simple (Darwin, except on x86_64) way of dealing with this was to
|
||||
// assume that any reference to a temporary symbol *must* be a temporary
|
||||
// symbol in the same atom, unless the sections differ. Therefore, any
|
||||
// PCrel relocation to a temporary symbol (in the same section) is fully
|
||||
// symbol in the same atom, unless the sections differ. Therefore, any PCrel
|
||||
// relocation to a temporary symbol (in the same section) is fully
|
||||
// resolved. This also works in conjunction with absolutized .set, which
|
||||
// requires the compiler to use .set to absolutize the differences between
|
||||
// symbols which the compiler knows to be assembly time constants, so we
|
||||
// don't need to worry about considering symbol differences fully
|
||||
// resolved.
|
||||
// don't need to worry about considering symbol differences fully resolved.
|
||||
|
||||
if (!Asm.getBackend().hasReliableSymbolDifference()) {
|
||||
if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB)
|
||||
@ -1447,9 +1571,9 @@ public:
|
||||
|
||||
// Otherwise, we can't prove this is fully resolved.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
|
||||
void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
|
||||
unsigned NumSections = Asm.size();
|
||||
|
||||
// The section data starts after the header, the segment load command (and
|
||||
@ -1468,8 +1592,8 @@ public:
|
||||
macho::DysymtabLoadCommandSize);
|
||||
}
|
||||
|
||||
// Compute the total size of the section data, as well as its file size and
|
||||
// vm size.
|
||||
// Compute the total size of the section data, as well as its file size and vm
|
||||
// size.
|
||||
uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
|
||||
macho::Header32Size) + LoadCommandsSize;
|
||||
uint64_t SectionDataSize = 0;
|
||||
@ -1612,9 +1736,6 @@ public:
|
||||
// Write the string table.
|
||||
OS << StringTable.str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
|
||||
|
Loading…
Reference in New Issue
Block a user