mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-03 01:06:05 +00:00
llvm-mc/Mach-O: Support byte and fill value emission.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7178010a16
commit
0705fbf52f
@ -10,8 +10,11 @@
|
||||
#ifndef LLVM_MC_MCASSEMBLER_H
|
||||
#define LLVM_MC_MCASSEMBLER_H
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -25,7 +28,211 @@ class MCFragment : public ilist_node<MCFragment> {
|
||||
void operator=(const MCFragment&); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
MCFragment(MCSectionData *SD = 0);
|
||||
enum FragmentType {
|
||||
FT_Data,
|
||||
FT_Align,
|
||||
FT_Fill,
|
||||
FT_Org
|
||||
};
|
||||
|
||||
private:
|
||||
FragmentType Kind;
|
||||
|
||||
/// @name Assembler Backend Data
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
/// FileOffset - The offset of this section in the object file. This is ~0
|
||||
/// until initialized.
|
||||
uint64_t FileOffset;
|
||||
|
||||
/// FileSize - The size of this section in the object file. This is ~0 until
|
||||
/// initialized.
|
||||
uint64_t FileSize;
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
|
||||
|
||||
public:
|
||||
// Only for sentinel.
|
||||
MCFragment();
|
||||
virtual ~MCFragment();
|
||||
|
||||
FragmentType getKind() const { return Kind; }
|
||||
|
||||
// FIXME: This should be abstract, fix sentinel.
|
||||
virtual unsigned getMaxFileSize() const {
|
||||
assert(0 && "Invalid getMaxFileSize call !");
|
||||
};
|
||||
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
unsigned getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
void setFileSize(uint64_t Value) {
|
||||
assert(Value <= getMaxFileSize() && "Invalid file size!");
|
||||
FileSize = Value;
|
||||
}
|
||||
|
||||
uint64_t getFileOffset() const {
|
||||
assert(FileOffset != ~UINT64_C(0) && "File offset not set!");
|
||||
return FileOffset;
|
||||
}
|
||||
void setFileOffset(uint64_t Value) { FileOffset = Value; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *O) { return true; }
|
||||
};
|
||||
|
||||
class MCDataFragment : public MCFragment {
|
||||
SmallString<32> Contents;
|
||||
|
||||
public:
|
||||
MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {}
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
unsigned getMaxFileSize() const {
|
||||
return Contents.size();
|
||||
}
|
||||
|
||||
SmallString<32> &getContents() { return Contents; }
|
||||
const SmallString<32> &getContents() const { return Contents; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Data;
|
||||
}
|
||||
static bool classof(const MCDataFragment *) { return true; }
|
||||
};
|
||||
|
||||
class MCAlignFragment : public MCFragment {
|
||||
/// Alignment - The alignment to ensure, in bytes.
|
||||
unsigned Alignment;
|
||||
|
||||
/// Value - Value to use for filling padding bytes.
|
||||
int64_t Value;
|
||||
|
||||
/// ValueSize - The size of the integer (in bytes) of \arg Value.
|
||||
unsigned ValueSize;
|
||||
|
||||
/// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
|
||||
/// cannot be satisfied in this width then this fragment is ignored.
|
||||
unsigned MaxBytesToEmit;
|
||||
|
||||
public:
|
||||
MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
|
||||
unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
|
||||
: MCFragment(FT_Align, SD), Alignment(_Alignment),
|
||||
Value(_Value),ValueSize(_ValueSize),
|
||||
MaxBytesToEmit(_MaxBytesToEmit) {}
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
unsigned getMaxFileSize() const {
|
||||
return std::max(Alignment - 1, MaxBytesToEmit);
|
||||
}
|
||||
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
|
||||
unsigned getValueSize() const { return ValueSize; }
|
||||
|
||||
unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Align;
|
||||
}
|
||||
static bool classof(const MCAlignFragment *) { return true; }
|
||||
};
|
||||
|
||||
class MCFillFragment : public MCFragment {
|
||||
/// Value - Value to use for filling bytes.
|
||||
MCValue Value;
|
||||
|
||||
/// ValueSize - The size (in bytes) of \arg Value to use when filling.
|
||||
unsigned ValueSize;
|
||||
|
||||
/// Count - The number of copies of \arg Value to insert.
|
||||
uint64_t Count;
|
||||
|
||||
public:
|
||||
MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count,
|
||||
MCSectionData *SD = 0)
|
||||
: MCFragment(FT_Fill, SD),
|
||||
Value(_Value), ValueSize(_ValueSize), Count(_Count) {}
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
unsigned getMaxFileSize() const {
|
||||
return ValueSize * Count;
|
||||
}
|
||||
|
||||
MCValue getValue() const { return Value; }
|
||||
|
||||
unsigned getValueSize() const { return ValueSize; }
|
||||
|
||||
uint64_t getCount() const { return Count; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Fill;
|
||||
}
|
||||
static bool classof(const MCFillFragment *) { return true; }
|
||||
};
|
||||
|
||||
class MCOrgFragment : public MCFragment {
|
||||
/// Offset - The offset this fragment should start at.
|
||||
MCValue Offset;
|
||||
|
||||
/// Value - Value to use for filling bytes.
|
||||
int64_t Value;
|
||||
|
||||
/// ValueSize - The size (in bytes) of \arg Value to use when filling.
|
||||
unsigned ValueSize;
|
||||
|
||||
public:
|
||||
MCOrgFragment(MCValue _Offset, int64_t _Value, unsigned _ValueSize,
|
||||
MCSectionData *SD = 0)
|
||||
: MCFragment(FT_Org, SD),
|
||||
Offset(_Offset), Value(_Value), ValueSize(_ValueSize) {}
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
unsigned getMaxFileSize() const {
|
||||
// FIXME
|
||||
return 0;
|
||||
}
|
||||
|
||||
MCValue getOffset() const { return Offset; }
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
|
||||
unsigned getValueSize() const { return ValueSize; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Org;
|
||||
}
|
||||
static bool classof(const MCOrgFragment *) { return true; }
|
||||
};
|
||||
|
||||
// FIXME: Should this be a separate class, or just merged into MCSection? Since
|
||||
@ -38,6 +245,9 @@ class MCSectionData : public ilist_node<MCSectionData> {
|
||||
public:
|
||||
typedef iplist<MCFragment> FragmentListType;
|
||||
|
||||
typedef FragmentListType::const_iterator const_iterator;
|
||||
typedef FragmentListType::iterator iterator;
|
||||
|
||||
private:
|
||||
iplist<MCFragment> Fragments;
|
||||
const MCSection &Section;
|
||||
@ -50,10 +260,12 @@ private:
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
/// FileOffset - The offset of this section in the object file.
|
||||
/// FileOffset - The offset of this section in the object file. This is ~0
|
||||
/// until initialized.
|
||||
uint64_t FileOffset;
|
||||
|
||||
/// FileSize - The size of this section in the object file.
|
||||
/// FileSize - The size of this section in the object file. This is ~0 until
|
||||
/// initialized.
|
||||
uint64_t FileSize;
|
||||
|
||||
/// @}
|
||||
@ -63,26 +275,44 @@ public:
|
||||
MCSectionData();
|
||||
MCSectionData(const MCSection &Section, MCAssembler *A = 0);
|
||||
|
||||
const FragmentListType &getFragmentList() const { return Fragments; }
|
||||
FragmentListType &getFragmentList() { return Fragments; }
|
||||
|
||||
const MCSection &getSection() const { return Section; }
|
||||
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
void setAlignment(unsigned Value) { Alignment = Value; }
|
||||
|
||||
|
||||
/// @name Section List Access
|
||||
/// @{
|
||||
|
||||
const FragmentListType &getFragmentList() const { return Fragments; }
|
||||
FragmentListType &getFragmentList() { return Fragments; }
|
||||
|
||||
iterator begin() { return Fragments.begin(); }
|
||||
const_iterator begin() const { return Fragments.begin(); }
|
||||
|
||||
iterator end() { return Fragments.end(); }
|
||||
const_iterator end() const { return Fragments.end(); }
|
||||
|
||||
size_t size() const { return Fragments.size(); }
|
||||
|
||||
/// @}
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
unsigned getFileSize() const { return FileSize; }
|
||||
unsigned getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
void setFileSize(uint64_t Value) { FileSize = Value; }
|
||||
|
||||
uint64_t getFileOffset() const { return FileOffset; }
|
||||
uint64_t getFileOffset() const {
|
||||
assert(FileOffset != ~UINT64_C(0) && "File offset not set!");
|
||||
return FileOffset;
|
||||
}
|
||||
void setFileOffset(uint64_t Value) { FileOffset = Value; }
|
||||
|
||||
void WriteFileData(raw_ostream &OS) const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
@ -101,6 +331,12 @@ private:
|
||||
|
||||
iplist<MCSectionData> Sections;
|
||||
|
||||
private:
|
||||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||
/// \arg SD, and update the section size. The section file offset should
|
||||
/// already have been computed.
|
||||
void LayoutSection(MCSectionData &SD);
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
///
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachOWriterInfo.h"
|
||||
|
||||
@ -48,17 +49,37 @@ public:
|
||||
/// @name Helper Methods
|
||||
/// @{
|
||||
|
||||
void Write8(uint8_t Value) {
|
||||
OS << char(Value);
|
||||
}
|
||||
|
||||
void Write16(uint16_t Value) {
|
||||
if (IsLSB) {
|
||||
Write8(uint8_t(Value >> 0));
|
||||
Write8(uint8_t(Value >> 8));
|
||||
} else {
|
||||
Write8(uint8_t(Value >> 8));
|
||||
Write8(uint8_t(Value >> 0));
|
||||
}
|
||||
}
|
||||
|
||||
void Write32(uint32_t Value) {
|
||||
if (IsLSB) {
|
||||
OS << char(Value >> 0);
|
||||
OS << char(Value >> 8);
|
||||
OS << char(Value >> 16);
|
||||
OS << char(Value >> 24);
|
||||
Write16(uint16_t(Value >> 0));
|
||||
Write16(uint16_t(Value >> 16));
|
||||
} else {
|
||||
OS << char(Value >> 24);
|
||||
OS << char(Value >> 16);
|
||||
OS << char(Value >> 8);
|
||||
OS << char(Value >> 0);
|
||||
Write16(uint16_t(Value >> 16));
|
||||
Write16(uint16_t(Value >> 0));
|
||||
}
|
||||
}
|
||||
|
||||
void Write64(uint64_t Value) {
|
||||
if (IsLSB) {
|
||||
Write32(uint32_t(Value >> 0));
|
||||
Write32(uint32_t(Value >> 32));
|
||||
} else {
|
||||
Write32(uint32_t(Value >> 32));
|
||||
Write32(uint32_t(Value >> 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +136,12 @@ public:
|
||||
Write32(CmdSize);
|
||||
}
|
||||
|
||||
void WriteSegmentLoadCommand32(unsigned NumSections) {
|
||||
/// WriteSegmentLoadCommand32 - Write a 32-bit segment load command.
|
||||
///
|
||||
/// \arg NumSections - The number of sections in this segment.
|
||||
/// \arg SectionDataSize - The total size of the sections.
|
||||
void WriteSegmentLoadCommand32(unsigned NumSections,
|
||||
uint64_t SectionDataSize) {
|
||||
// struct segment_command (56 bytes)
|
||||
|
||||
uint64_t Start = OS.tell();
|
||||
@ -126,10 +152,10 @@ public:
|
||||
|
||||
WriteString("", 16);
|
||||
Write32(0); // vmaddr
|
||||
Write32(0); // vmsize
|
||||
Write32(SectionDataSize); // vmsize
|
||||
Write32(Header32Size + SegmentLoadCommand32Size +
|
||||
NumSections * Section32Size); // file offset
|
||||
Write32(0); // file size
|
||||
Write32(SectionDataSize); // file size
|
||||
Write32(0x7); // maxprot
|
||||
Write32(0x7); // initprot
|
||||
Write32(NumSections);
|
||||
@ -169,12 +195,21 @@ public:
|
||||
|
||||
/* *** */
|
||||
|
||||
MCFragment::MCFragment(MCSectionData *SD)
|
||||
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
|
||||
}
|
||||
|
||||
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *SD)
|
||||
: Kind(_Kind),
|
||||
FileOffset(~UINT64_C(0)),
|
||||
FileSize(~UINT64_C(0))
|
||||
{
|
||||
if (SD)
|
||||
SD->getFragmentList().push_back(this);
|
||||
}
|
||||
|
||||
MCFragment::~MCFragment() {
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
||||
MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
|
||||
@ -182,17 +217,13 @@ MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
|
||||
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
||||
: Section(_Section),
|
||||
Alignment(1),
|
||||
FileOffset(0),
|
||||
FileSize(0)
|
||||
FileOffset(~UINT64_C(0)),
|
||||
FileSize(~UINT64_C(0))
|
||||
{
|
||||
if (A)
|
||||
A->getSectionList().push_back(this);
|
||||
}
|
||||
|
||||
void MCSectionData::WriteFileData(raw_ostream &OS) const {
|
||||
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
||||
MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
|
||||
@ -200,21 +231,97 @@ MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
|
||||
MCAssembler::~MCAssembler() {
|
||||
}
|
||||
|
||||
void MCAssembler::LayoutSection(MCSectionData &SD) {
|
||||
uint64_t Offset = SD.getFileOffset();
|
||||
|
||||
for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
|
||||
MCFragment &F = *it;
|
||||
F.setFileOffset(Offset);
|
||||
F.setFileSize(F.getMaxFileSize());
|
||||
Offset += F.getFileSize();
|
||||
}
|
||||
|
||||
// FIXME: Pad section?
|
||||
SD.setFileSize(Offset - SD.getFileOffset());
|
||||
}
|
||||
|
||||
/// WriteFileData - Write the \arg F data to the output file.
|
||||
static void WriteFileData(raw_ostream &OS, const MCFragment &F,
|
||||
MachObjectWriter &MOW) {
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
|
||||
// FIXME: Embed in fragments instead?
|
||||
switch (F.getKind()) {
|
||||
default:
|
||||
assert(0 && "Invalid section kind!");
|
||||
|
||||
case MCFragment::FT_Data:
|
||||
OS << cast<MCDataFragment>(F).getContents().str();
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Align:
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
|
||||
case MCFragment::FT_Fill: {
|
||||
MCFillFragment &FF = cast<MCFillFragment>(F);
|
||||
|
||||
if (!FF.getValue().isAbsolute())
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
|
||||
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
|
||||
switch (FF.getValueSize()) {
|
||||
default:
|
||||
assert(0 && "Invalid size!");
|
||||
case 1: MOW.Write8 (uint8_t (FF.getValue().getConstant())); break;
|
||||
case 2: MOW.Write16(uint16_t(FF.getValue().getConstant())); break;
|
||||
case 4: MOW.Write32(uint32_t(FF.getValue().getConstant())); break;
|
||||
case 8: MOW.Write64(uint64_t(FF.getValue().getConstant())); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MCFragment::FT_Org:
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
}
|
||||
|
||||
assert(OS.tell() - Start == F.getFileSize());
|
||||
}
|
||||
|
||||
/// WriteFileData - Write the \arg SD data to the output file.
|
||||
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
|
||||
MachObjectWriter &MOW) {
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
|
||||
for (MCSectionData::const_iterator it = SD.begin(),
|
||||
ie = SD.end(); it != ie; ++it)
|
||||
WriteFileData(OS, *it, MOW);
|
||||
|
||||
assert(OS.tell() - Start == SD.getFileSize());
|
||||
}
|
||||
|
||||
void MCAssembler::Finish() {
|
||||
unsigned NumSections = Sections.size();
|
||||
|
||||
// Compute the file offsets so we can write in a single pass.
|
||||
|
||||
// Layout the sections and fragments.
|
||||
uint64_t Offset = MachObjectWriter::getPrologSize32(NumSections);
|
||||
uint64_t SectionDataSize = 0;
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
it->setFileOffset(Offset);
|
||||
|
||||
LayoutSection(*it);
|
||||
|
||||
Offset += it->getFileSize();
|
||||
SectionDataSize += it->getFileSize();
|
||||
}
|
||||
|
||||
MachObjectWriter MOW(OS);
|
||||
|
||||
// Write the prolog, starting with the header and load command...
|
||||
MOW.WriteHeader32(NumSections);
|
||||
MOW.WriteSegmentLoadCommand32(NumSections);
|
||||
MOW.WriteSegmentLoadCommand32(NumSections, SectionDataSize);
|
||||
|
||||
// ... and then the section headers.
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
||||
@ -222,7 +329,7 @@ void MCAssembler::Finish() {
|
||||
|
||||
// Finally, write the section data.
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
||||
it->WriteFileData(OS);
|
||||
|
||||
WriteFileData(OS, *it, MOW);
|
||||
|
||||
OS.flush();
|
||||
}
|
||||
|
@ -139,22 +139,28 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitBytes(const StringRef &Data) {
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
MCDataFragment *DF = new MCDataFragment(CurSectionData);
|
||||
DF->getContents().append(Data.begin(), Data.end());
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) {
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
new MCFillFragment(Value, Size, 1, CurSectionData);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,
|
||||
int64_t Value, unsigned ValueSize,
|
||||
unsigned MaxBytesToEmit) {
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
|
||||
CurSectionData);
|
||||
|
||||
// Update the maximum alignment on the current section if necessary
|
||||
if (ByteAlignment > CurSectionData->getAlignment())
|
||||
CurSectionData->setAlignment(ByteAlignment);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset,
|
||||
unsigned char Value) {
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
new MCOrgFragment(Offset, Value, 1, CurSectionData);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
|
||||
|
60
test/MC/MachO/data.s
Normal file
60
test/MC/MachO/data.s
Normal file
@ -0,0 +1,60 @@
|
||||
// RUN: llvm-mc %s -filetype=obj -o - | macho-dump | FileCheck %s
|
||||
|
||||
.data
|
||||
.ascii "hello"
|
||||
.byte 0xAB
|
||||
.short 0xABCD
|
||||
.long 0xABCDABCD
|
||||
.quad 0xABCDABCDABCDABCD
|
||||
|
||||
// CHECK: ('cputype', 7)
|
||||
// CHECK: ('cpusubtype', 3)
|
||||
// CHECK: ('filetype', 1)
|
||||
// CHECK: ('num_load_commands', 1)
|
||||
// CHECK: ('load_commands_size', 192)
|
||||
// CHECK: ('flag', 0)
|
||||
// CHECK: ('load_commands', [
|
||||
// CHECK: # Load Command 0
|
||||
// CHECK: (('command', 1)
|
||||
// CHECK: ('size', 192)
|
||||
// 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', 20)
|
||||
// CHECK: ('file_offset', 220)
|
||||
// CHECK: ('file_size', 20)
|
||||
// CHECK: ('maxprot', 7)
|
||||
// CHECK: ('initprot', 7)
|
||||
// CHECK: ('num_sections', 2)
|
||||
// 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', 220)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x80000000)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// 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', 20)
|
||||
// CHECK: ('offset', 220)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x0)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
|
||||
// FIXME: Dump contents, so we can check those too.
|
Loading…
x
Reference in New Issue
Block a user