mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
llvm-mc/Mach-O: Add support for relocations.
- I haven't really tried to find the "right" way to store the fixups or apply them, yet. This works, but isn't particularly elegant or fast. - Still no evaluation support, so we don't actually ever not turn a fixup into a relocation entry. llvm-svn: 80089
This commit is contained in:
parent
45d03f2bbb
commit
8c38017009
@ -246,11 +246,45 @@ class MCSectionData : public ilist_node<MCSectionData> {
|
||||
void operator=(const MCSectionData&); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
/// Fixup - Represent a fixed size region of bytes inside some fragment which
|
||||
/// needs to be rewritten. This region will either be rewritten by the
|
||||
/// assembler or cause a relocation entry to be generated.
|
||||
struct Fixup {
|
||||
/// Fragment - The fragment containing the fixup.
|
||||
MCFragment *Fragment;
|
||||
|
||||
/// Offset - The offset inside the fragment which needs to be rewritten.
|
||||
uint64_t Offset;
|
||||
|
||||
/// Value - The expression to eventually write into the fragment.
|
||||
//
|
||||
// FIXME: We could probably get away with requiring the client to pass in an
|
||||
// owned reference whose lifetime extends past that of the fixup.
|
||||
MCValue Value;
|
||||
|
||||
/// Size - The fixup size.
|
||||
unsigned Size;
|
||||
|
||||
/// FixedValue - The value to replace the fix up by.
|
||||
//
|
||||
// FIXME: This should not be here.
|
||||
uint64_t FixedValue;
|
||||
|
||||
public:
|
||||
Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCValue &_Value,
|
||||
unsigned _Size)
|
||||
: Fragment(&_Fragment), Offset(_Offset), Value(_Value), Size(_Size),
|
||||
FixedValue(0) {}
|
||||
};
|
||||
|
||||
typedef iplist<MCFragment> FragmentListType;
|
||||
|
||||
typedef FragmentListType::const_iterator const_iterator;
|
||||
typedef FragmentListType::iterator iterator;
|
||||
|
||||
typedef std::vector<Fixup>::const_iterator const_fixup_iterator;
|
||||
typedef std::vector<Fixup>::iterator fixup_iterator;
|
||||
|
||||
private:
|
||||
iplist<MCFragment> Fragments;
|
||||
const MCSection &Section;
|
||||
@ -274,6 +308,12 @@ private:
|
||||
/// initialized.
|
||||
uint64_t FileSize;
|
||||
|
||||
/// LastFixupLookup - Cache for the last looked up fixup.
|
||||
mutable unsigned LastFixupLookup;
|
||||
|
||||
/// Fixups - The list of fixups in this section.
|
||||
std::vector<Fixup> Fixups;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
@ -302,12 +342,40 @@ public:
|
||||
|
||||
bool empty() const { return Fragments.empty(); }
|
||||
|
||||
/// @}
|
||||
/// @name Fixup Access
|
||||
/// @{
|
||||
|
||||
std::vector<Fixup> &getFixups() {
|
||||
return Fixups;
|
||||
}
|
||||
|
||||
fixup_iterator fixup_begin() {
|
||||
return Fixups.begin();
|
||||
}
|
||||
|
||||
fixup_iterator fixup_end() {
|
||||
return Fixups.end();
|
||||
}
|
||||
|
||||
size_t fixup_size() const { return Fixups.size(); }
|
||||
|
||||
/// @}
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
/// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
|
||||
/// Offset.
|
||||
///
|
||||
/// If multiple fixups exist for the same fragment and offset it is undefined
|
||||
/// which one is returned.
|
||||
//
|
||||
// FIXME: This isn't horribly slow in practice, but there are much nicer
|
||||
// solutions to applying the fixups.
|
||||
const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const;
|
||||
|
||||
uint64_t getAddress() const {
|
||||
assert(Address != ~UINT64_C(0) && "Address not set!");
|
||||
return Address;
|
||||
|
@ -42,6 +42,7 @@ class MachObjectWriter {
|
||||
static const unsigned SymtabLoadCommandSize = 24;
|
||||
static const unsigned DysymtabLoadCommandSize = 80;
|
||||
static const unsigned Nlist32Size = 12;
|
||||
static const unsigned RelocationInfoSize = 8;
|
||||
|
||||
enum HeaderFileType {
|
||||
HFT_Object = 0x1
|
||||
@ -77,6 +78,19 @@ class MachObjectWriter {
|
||||
ISF_Absolute = 0x40000000
|
||||
};
|
||||
|
||||
/// RelocationFlags - Special flags for addresses.
|
||||
enum RelocationFlags {
|
||||
RF_Scattered = 0x80000000
|
||||
};
|
||||
|
||||
enum RelocationInfoType {
|
||||
RIT_Vanilla = 0,
|
||||
RIT_Pair = 1,
|
||||
RIT_Difference = 2,
|
||||
RIT_PreboundLazyPointer = 3,
|
||||
RIT_LocalDifference = 4
|
||||
};
|
||||
|
||||
/// MachSymbolData - Helper struct for containing some precomputed information
|
||||
/// on symbols.
|
||||
struct MachSymbolData {
|
||||
@ -205,7 +219,8 @@ public:
|
||||
assert(OS.tell() - Start == SegmentLoadCommand32Size);
|
||||
}
|
||||
|
||||
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset) {
|
||||
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations) {
|
||||
// struct section (68 bytes)
|
||||
|
||||
uint64_t Start = OS.tell();
|
||||
@ -222,8 +237,8 @@ public:
|
||||
|
||||
assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
|
||||
Write32(Log2_32(SD.getAlignment()));
|
||||
Write32(0); // file offset of relocation entries
|
||||
Write32(0); // number of relocation entrions
|
||||
Write32(NumRelocations ? RelocationsStart : 0);
|
||||
Write32(NumRelocations);
|
||||
Write32(Section.getTypeAndAttributes());
|
||||
Write32(0); // reserved1
|
||||
Write32(Section.getStubSize()); // reserved2
|
||||
@ -332,6 +347,126 @@ public:
|
||||
Write32(Address);
|
||||
}
|
||||
|
||||
struct MachRelocationEntry {
|
||||
uint32_t Word0;
|
||||
uint32_t Word1;
|
||||
};
|
||||
void ComputeScatteredRelocationInfo(MCAssembler &Asm,
|
||||
MCSectionData::Fixup &Fixup,
|
||||
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
|
||||
std::vector<MachRelocationEntry> &Relocs) {
|
||||
uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
|
||||
unsigned IsPCRel = 0;
|
||||
unsigned Type = RIT_Vanilla;
|
||||
|
||||
// See <reloc.h>.
|
||||
|
||||
const MCSymbol *A = Fixup.Value.getSymA();
|
||||
MCSymbolData *SD = SymbolMap.lookup(A);
|
||||
uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
|
||||
uint32_t Value2 = 0;
|
||||
|
||||
if (const MCSymbol *B = Fixup.Value.getSymB()) {
|
||||
Type = RIT_LocalDifference;
|
||||
|
||||
MCSymbolData *SD = SymbolMap.lookup(B);
|
||||
Value2 = SD->getFragment()->getAddress() + SD->getOffset();
|
||||
}
|
||||
|
||||
unsigned Log2Size = Log2_32(Fixup.Size);
|
||||
assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
|
||||
|
||||
// The value which goes in the fixup is current value of the expression.
|
||||
Fixup.FixedValue = Value - Value2 + Fixup.Value.getConstant();
|
||||
|
||||
MachRelocationEntry MRE;
|
||||
MRE.Word0 = ((Address << 0) |
|
||||
(Type << 24) |
|
||||
(Log2Size << 28) |
|
||||
(IsPCRel << 30) |
|
||||
RF_Scattered);
|
||||
MRE.Word1 = Value;
|
||||
Relocs.push_back(MRE);
|
||||
|
||||
if (Type == RIT_LocalDifference) {
|
||||
Type = RIT_Pair;
|
||||
|
||||
MachRelocationEntry MRE;
|
||||
MRE.Word0 = ((0 << 0) |
|
||||
(Type << 24) |
|
||||
(Log2Size << 28) |
|
||||
(0 << 30) |
|
||||
RF_Scattered);
|
||||
MRE.Word1 = Value2;
|
||||
Relocs.push_back(MRE);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeRelocationInfo(MCAssembler &Asm,
|
||||
MCSectionData::Fixup &Fixup,
|
||||
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
|
||||
std::vector<MachRelocationEntry> &Relocs) {
|
||||
// If this is a local symbol plus an offset or a difference, then we need a
|
||||
// scattered relocation entry.
|
||||
if (Fixup.Value.getSymB()) // a - b
|
||||
return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
|
||||
if (Fixup.Value.getSymA() && Fixup.Value.getConstant())
|
||||
if (!Fixup.Value.getSymA()->isUndefined())
|
||||
return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
|
||||
|
||||
// See <reloc.h>.
|
||||
uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
|
||||
uint32_t Value = 0;
|
||||
unsigned Index = 0;
|
||||
unsigned IsPCRel = 0;
|
||||
unsigned IsExtern = 0;
|
||||
unsigned Type = 0;
|
||||
|
||||
if (Fixup.Value.isAbsolute()) { // constant
|
||||
// SymbolNum of 0 indicates the absolute section.
|
||||
Type = RIT_Vanilla;
|
||||
Value = 0;
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
} else {
|
||||
const MCSymbol *Symbol = Fixup.Value.getSymA();
|
||||
MCSymbolData *SD = SymbolMap.lookup(Symbol);
|
||||
|
||||
if (Symbol->isUndefined()) {
|
||||
IsExtern = 1;
|
||||
Index = SD->getIndex();
|
||||
Value = 0;
|
||||
} else {
|
||||
// The index is the section ordinal.
|
||||
//
|
||||
// FIXME: O(N)
|
||||
Index = 1;
|
||||
for (MCAssembler::iterator it = Asm.begin(),
|
||||
ie = Asm.end(); it != ie; ++it, ++Index)
|
||||
if (&*it == SD->getFragment()->getParent())
|
||||
break;
|
||||
Value = SD->getFragment()->getAddress() + SD->getOffset();
|
||||
}
|
||||
|
||||
Type = RIT_Vanilla;
|
||||
}
|
||||
|
||||
// The value which goes in the fixup is current value of the expression.
|
||||
Fixup.FixedValue = Value + Fixup.Value.getConstant();
|
||||
|
||||
unsigned Log2Size = Log2_32(Fixup.Size);
|
||||
assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
|
||||
|
||||
// struct relocation_info (8 bytes)
|
||||
MachRelocationEntry MRE;
|
||||
MRE.Word0 = Address;
|
||||
MRE.Word1 = ((Index << 0) |
|
||||
(IsPCRel << 24) |
|
||||
(Log2Size << 25) |
|
||||
(IsExtern << 27) |
|
||||
(Type << 28));
|
||||
Relocs.push_back(MRE);
|
||||
}
|
||||
|
||||
void BindIndirectSymbols(MCAssembler &Asm,
|
||||
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap) {
|
||||
// This is the point where 'as' creates actual symbols for indirect symbols
|
||||
@ -543,9 +678,31 @@ public:
|
||||
WriteSegmentLoadCommand32(NumSections, SectionDataStart, SectionDataSize);
|
||||
|
||||
// ... and then the section headers.
|
||||
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
|
||||
WriteSection32(*it, SectionDataStart + it->getAddress());
|
||||
//
|
||||
// We also compute the section relocations while we do this. Note that
|
||||
// compute relocation info will also update the fixup to have the correct
|
||||
// value; this will be overwrite the appropriate data in the fragment when
|
||||
// it is written.
|
||||
std::vector<MachRelocationEntry> RelocInfos;
|
||||
uint64_t RelocTableEnd = SectionDataEnd;
|
||||
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
|
||||
++it) {
|
||||
MCSectionData &SD = *it;
|
||||
|
||||
// The assembler writes relocations in the reverse order they were seen.
|
||||
//
|
||||
// FIXME: It is probably more complicated than this.
|
||||
unsigned NumRelocsStart = RelocInfos.size();
|
||||
for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
|
||||
ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
|
||||
RelocInfos);
|
||||
|
||||
unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
|
||||
uint64_t SectionStart = SectionDataStart + SD.getAddress();
|
||||
WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs);
|
||||
RelocTableEnd += NumRelocs * RelocationInfoSize;
|
||||
}
|
||||
|
||||
// Write the symbol table load command, if used.
|
||||
if (NumSymbols) {
|
||||
unsigned FirstLocalSymbol = 0;
|
||||
@ -562,10 +719,10 @@ public:
|
||||
|
||||
// If used, the indirect symbols are written after the section data.
|
||||
if (NumIndirectSymbols)
|
||||
IndirectSymbolOffset = SectionDataEnd;
|
||||
IndirectSymbolOffset = RelocTableEnd;
|
||||
|
||||
// The symbol table is written after the indirect symbol data.
|
||||
uint64_t SymbolTableOffset = SectionDataEnd + IndirectSymbolSize;
|
||||
uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
|
||||
|
||||
// The string table is written after symbol table.
|
||||
uint64_t StringTableOffset =
|
||||
@ -583,6 +740,12 @@ public:
|
||||
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
|
||||
WriteFileData(OS, *it, *this);
|
||||
|
||||
// Write the relocation entries.
|
||||
for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) {
|
||||
Write32(RelocInfos[i].Word0);
|
||||
Write32(RelocInfos[i].Word1);
|
||||
}
|
||||
|
||||
// Write the symbol table data, if used.
|
||||
if (NumSymbols) {
|
||||
// Write the indirect symbol entries.
|
||||
@ -657,12 +820,35 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
||||
Alignment(1),
|
||||
Address(~UINT64_C(0)),
|
||||
Size(~UINT64_C(0)),
|
||||
FileSize(~UINT64_C(0))
|
||||
FileSize(~UINT64_C(0)),
|
||||
LastFixupLookup(~0)
|
||||
{
|
||||
if (A)
|
||||
A->getSectionList().push_back(this);
|
||||
}
|
||||
|
||||
const MCSectionData::Fixup *
|
||||
MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const {
|
||||
// Use a one level cache to turn the common case of accessing the fixups in
|
||||
// order into O(1) instead of O(N).
|
||||
unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
|
||||
if (i >= End)
|
||||
i = 0;
|
||||
while (Count--) {
|
||||
const Fixup &F = Fixups[i];
|
||||
if (F.Fragment == Fragment && F.Offset == Offset) {
|
||||
LastFixupLookup = i;
|
||||
return &F;
|
||||
}
|
||||
|
||||
++i;
|
||||
if (i == End)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
||||
MCSymbolData::MCSymbolData() : Symbol(*(MCSymbol*)0) {}
|
||||
@ -705,10 +891,27 @@ void MCAssembler::LayoutSection(MCSectionData &SD, unsigned NextAlign) {
|
||||
}
|
||||
|
||||
case MCFragment::FT_Data:
|
||||
case MCFragment::FT_Fill:
|
||||
F.setFileSize(F.getMaxFileSize());
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Fill: {
|
||||
MCFillFragment &FF = cast<MCFillFragment>(F);
|
||||
|
||||
F.setFileSize(F.getMaxFileSize());
|
||||
|
||||
// If the fill value is constant, thats it.
|
||||
if (FF.getValue().isAbsolute())
|
||||
break;
|
||||
|
||||
// Otherwise, add fixups for the values.
|
||||
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
|
||||
MCSectionData::Fixup Fix(F, i * FF.getValueSize(),
|
||||
FF.getValue(),FF.getValueSize());
|
||||
SD.getFixups().push_back(Fix);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MCFragment::FT_Org: {
|
||||
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
||||
|
||||
@ -778,11 +981,20 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
|
||||
case MCFragment::FT_Fill: {
|
||||
MCFillFragment &FF = cast<MCFillFragment>(F);
|
||||
|
||||
int64_t Value = 0;
|
||||
if (!FF.getValue().isAbsolute())
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
int64_t Value = FF.getValue().getConstant();
|
||||
|
||||
Value = FF.getValue().getConstant();
|
||||
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
|
||||
if (!FF.getValue().isAbsolute()) {
|
||||
// Find the fixup.
|
||||
//
|
||||
// FIXME: Find a better way to write in the fixes.
|
||||
const MCSectionData::Fixup *Fixup =
|
||||
F.getParent()->LookupFixup(&F, i * FF.getValueSize());
|
||||
assert(Fixup && "Missing fixup for fill value!");
|
||||
Value = Fixup->FixedValue;
|
||||
}
|
||||
|
||||
switch (FF.getValueSize()) {
|
||||
default:
|
||||
assert(0 && "Invalid size!");
|
||||
|
227
test/MC/MachO/reloc.s
Normal file
227
test/MC/MachO/reloc.s
Normal file
@ -0,0 +1,227 @@
|
||||
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
|
||||
|
||||
.data
|
||||
.long undef
|
||||
.long (undef + 4)
|
||||
|
||||
.globl local_a_ext
|
||||
local_a_ext:
|
||||
.long local_a_ext
|
||||
|
||||
local_a:
|
||||
.long 0
|
||||
local_a_elt:
|
||||
.long 0
|
||||
local_b:
|
||||
.long local_b - local_c + 245
|
||||
.long 0
|
||||
local_c:
|
||||
.long 0
|
||||
|
||||
|
||||
.long local_a_elt + 1
|
||||
.long local_a_elt + 10
|
||||
.short local_a_elt + 20
|
||||
.byte local_a_elt + 89
|
||||
|
||||
.const
|
||||
|
||||
.long
|
||||
bar:
|
||||
.long local_a_elt - bar + 33
|
||||
|
||||
// CHECK: ('cputype', 7)
|
||||
// CHECK: ('cpusubtype', 3)
|
||||
// CHECK: ('filetype', 1)
|
||||
// CHECK: ('num_load_commands', 1)
|
||||
// CHECK: ('load_commands_size', 364)
|
||||
// CHECK: ('flag', 0)
|
||||
// CHECK: ('load_commands', [
|
||||
// CHECK: # Load Command 0
|
||||
// CHECK: (('command', 1)
|
||||
// CHECK: ('size', 260)
|
||||
// CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('vm_addr', 0)
|
||||
// CHECK: ('vm_size', 47)
|
||||
// CHECK: ('file_offset', 392)
|
||||
// CHECK: ('file_size', 47)
|
||||
// CHECK: ('maxprot', 7)
|
||||
// CHECK: ('initprot', 7)
|
||||
// CHECK: ('num_sections', 3)
|
||||
// CHECK: ('flags', 0)
|
||||
// CHECK: ('sections', [
|
||||
// CHECK: # Section 0
|
||||
// CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 0)
|
||||
// CHECK: ('size', 0)
|
||||
// CHECK: ('offset', 392)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x80000000)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ('_relocations', [
|
||||
// CHECK: ])
|
||||
// CHECK: ('_section_data', '')
|
||||
// CHECK: # Section 1
|
||||
// CHECK: (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 0)
|
||||
// CHECK: ('size', 43)
|
||||
// CHECK: ('offset', 392)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 440)
|
||||
// CHECK: ('num_reloc', 9)
|
||||
// CHECK: ('flags', 0x0)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ('_relocations', [
|
||||
// CHECK: # Relocation 0
|
||||
// CHECK: (('word-0', 0x8000002a),
|
||||
// CHECK: ('word-1', 0x10)),
|
||||
// CHECK: # Relocation 1
|
||||
// CHECK: (('word-0', 0x90000028),
|
||||
// CHECK: ('word-1', 0x10)),
|
||||
// CHECK: # Relocation 2
|
||||
// CHECK: (('word-0', 0xa0000024),
|
||||
// CHECK: ('word-1', 0x10)),
|
||||
// CHECK: # Relocation 3
|
||||
// CHECK: (('word-0', 0xa0000020),
|
||||
// CHECK: ('word-1', 0x10)),
|
||||
// CHECK: # Relocation 4
|
||||
// CHECK: (('word-0', 0xa4000014),
|
||||
// CHECK: ('word-1', 0x14)),
|
||||
// CHECK: # Relocation 5
|
||||
// CHECK: (('word-0', 0xa1000000),
|
||||
// CHECK: ('word-1', 0x1c)),
|
||||
// CHECK: # Relocation 6
|
||||
// CHECK: (('word-0', 0x8),
|
||||
// CHECK: ('word-1', 0x4000002)),
|
||||
// CHECK: # Relocation 7
|
||||
// CHECK: (('word-0', 0x4),
|
||||
// CHECK: ('word-1', 0xc000006)),
|
||||
// CHECK: # Relocation 8
|
||||
// CHECK: (('word-0', 0x0),
|
||||
// CHECK: ('word-1', 0xc000006)),
|
||||
// CHECK: ])
|
||||
// CHECK: ('_section_data', '\x00\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x1a\x00\x00\x00$\x00i')
|
||||
// CHECK: # Section 2
|
||||
// CHECK: (('section_name', '__const\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 43)
|
||||
// CHECK: ('size', 4)
|
||||
// CHECK: ('offset', 435)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 512)
|
||||
// CHECK: ('num_reloc', 2)
|
||||
// CHECK: ('flags', 0x0)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ('_relocations', [
|
||||
// CHECK: # Relocation 0
|
||||
// CHECK: (('word-0', 0xa4000000),
|
||||
// CHECK: ('word-1', 0x10)),
|
||||
// CHECK: # Relocation 1
|
||||
// CHECK: (('word-0', 0xa1000000),
|
||||
// CHECK: ('word-1', 0x2b)),
|
||||
// CHECK: ])
|
||||
// CHECK: ('_section_data', '\x06\x00\x00\x00')
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 1
|
||||
// CHECK: (('command', 2)
|
||||
// CHECK: ('size', 24)
|
||||
// CHECK: ('symoff', 528)
|
||||
// CHECK: ('nsyms', 7)
|
||||
// CHECK: ('stroff', 612)
|
||||
// CHECK: ('strsize', 60)
|
||||
// CHECK: ('_string_data', '\x00undef\x00local_a_ext\x00local_a\x00local_a_elt\x00local_b\x00local_c\x00bar\x00\x00')
|
||||
// CHECK: ('_symbols', [
|
||||
// CHECK: # Symbol 0
|
||||
// CHECK: (('n_strx', 19)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 12)
|
||||
// CHECK: ('_string', 'local_a')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 1
|
||||
// CHECK: (('n_strx', 27)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 16)
|
||||
// CHECK: ('_string', 'local_a_elt')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 2
|
||||
// CHECK: (('n_strx', 39)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 20)
|
||||
// CHECK: ('_string', 'local_b')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 3
|
||||
// CHECK: (('n_strx', 47)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 28)
|
||||
// CHECK: ('_string', 'local_c')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 4
|
||||
// CHECK: (('n_strx', 55)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 3)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 43)
|
||||
// CHECK: ('_string', 'bar')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 5
|
||||
// CHECK: (('n_strx', 7)
|
||||
// CHECK: ('n_type', 0xf)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 8)
|
||||
// CHECK: ('_string', 'local_a_ext')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 6
|
||||
// CHECK: (('n_strx', 1)
|
||||
// CHECK: ('n_type', 0x1)
|
||||
// CHECK: ('n_sect', 0)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 0)
|
||||
// CHECK: ('_string', 'undef')
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 2
|
||||
// CHECK: (('command', 11)
|
||||
// CHECK: ('size', 80)
|
||||
// CHECK: ('ilocalsym', 0)
|
||||
// CHECK: ('nlocalsym', 5)
|
||||
// CHECK: ('iextdefsym', 5)
|
||||
// CHECK: ('nextdefsym', 1)
|
||||
// CHECK: ('iundefsym', 6)
|
||||
// CHECK: ('nundefsym', 1)
|
||||
// CHECK: ('tocoff', 0)
|
||||
// CHECK: ('ntoc', 0)
|
||||
// CHECK: ('modtaboff', 0)
|
||||
// CHECK: ('nmodtab', 0)
|
||||
// CHECK: ('extrefsymoff', 0)
|
||||
// CHECK: ('nextrefsyms', 0)
|
||||
// CHECK: ('indirectsymoff', 0)
|
||||
// CHECK: ('nindirectsyms', 0)
|
||||
// CHECK: ('extreloff', 0)
|
||||
// CHECK: ('nextrel', 0)
|
||||
// CHECK: ('locreloff', 0)
|
||||
// CHECK: ('nlocrel', 0)
|
||||
// CHECK: ('_indirect_symbols', [
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
Loading…
Reference in New Issue
Block a user