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:
Daniel Dunbar
2009-08-21 18:29:01 +00:00
parent 7178010a16
commit 0705fbf52f
4 changed files with 446 additions and 37 deletions

View File

@@ -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();
}