mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
MC/Mach-O: Initial x86_64 support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98454 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Target/TargetRegistry.h"
|
||||
#include "llvm/Target/TargetAsmBackend.h"
|
||||
|
||||
// FIXME: Gross.
|
||||
@@ -86,14 +87,19 @@ class MachObjectWriter {
|
||||
Header_Magic64 = 0xFEEDFACF
|
||||
};
|
||||
|
||||
static const unsigned Header32Size = 28;
|
||||
static const unsigned Header64Size = 32;
|
||||
static const unsigned SegmentLoadCommand32Size = 56;
|
||||
static const unsigned Section32Size = 68;
|
||||
static const unsigned SymtabLoadCommandSize = 24;
|
||||
static const unsigned DysymtabLoadCommandSize = 80;
|
||||
static const unsigned Nlist32Size = 12;
|
||||
static const unsigned RelocationInfoSize = 8;
|
||||
enum {
|
||||
Header32Size = 28,
|
||||
Header64Size = 32,
|
||||
SegmentLoadCommand32Size = 56,
|
||||
SegmentLoadCommand64Size = 72,
|
||||
Section32Size = 68,
|
||||
Section64Size = 80,
|
||||
SymtabLoadCommandSize = 24,
|
||||
DysymtabLoadCommandSize = 80,
|
||||
Nlist32Size = 12,
|
||||
Nlist64Size = 16,
|
||||
RelocationInfoSize = 8
|
||||
};
|
||||
|
||||
enum HeaderFileType {
|
||||
HFT_Object = 0x1
|
||||
@@ -106,7 +112,8 @@ class MachObjectWriter {
|
||||
enum LoadCommandType {
|
||||
LCT_Segment = 0x1,
|
||||
LCT_Symtab = 0x2,
|
||||
LCT_Dysymtab = 0xb
|
||||
LCT_Dysymtab = 0xb,
|
||||
LCT_Segment64 = 0x19
|
||||
};
|
||||
|
||||
// See <mach-o/nlist.h>.
|
||||
@@ -161,11 +168,12 @@ class MachObjectWriter {
|
||||
};
|
||||
|
||||
raw_ostream &OS;
|
||||
bool IsLSB;
|
||||
unsigned Is64Bit : 1;
|
||||
unsigned IsLSB : 1;
|
||||
|
||||
public:
|
||||
MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
|
||||
: OS(_OS), IsLSB(_IsLSB) {
|
||||
MachObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool _IsLSB = true)
|
||||
: OS(_OS), Is64Bit(_Is64Bit), IsLSB(_IsLSB) {
|
||||
}
|
||||
|
||||
/// @name Helper Methods
|
||||
@@ -222,22 +230,23 @@ public:
|
||||
|
||||
/// @}
|
||||
|
||||
void WriteHeader32(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
bool SubsectionsViaSymbols) {
|
||||
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
bool SubsectionsViaSymbols) {
|
||||
uint32_t Flags = 0;
|
||||
|
||||
if (SubsectionsViaSymbols)
|
||||
Flags |= HF_SubsectionsViaSymbols;
|
||||
|
||||
// struct mach_header (28 bytes)
|
||||
// struct mach_header (28 bytes) or
|
||||
// struct mach_header_64 (32 bytes)
|
||||
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
|
||||
Write32(Header_Magic32);
|
||||
Write32(Is64Bit ? Header_Magic64 : Header_Magic32);
|
||||
|
||||
// FIXME: Support cputype.
|
||||
Write32(MachO::CPUTypeI386);
|
||||
Write32(Is64Bit ? MachO::CPUTypeX86_64 : MachO::CPUTypeI386);
|
||||
// FIXME: Support cpusubtype.
|
||||
Write32(MachO::CPUSubType_I386_ALL);
|
||||
Write32(HFT_Object);
|
||||
@@ -245,48 +254,62 @@ public:
|
||||
// segment.
|
||||
Write32(LoadCommandsSize);
|
||||
Write32(Flags);
|
||||
if (Is64Bit)
|
||||
Write32(0); // reserved
|
||||
|
||||
assert(OS.tell() - Start == Header32Size);
|
||||
assert(OS.tell() - Start == Is64Bit ? Header64Size : Header32Size);
|
||||
}
|
||||
|
||||
/// WriteSegmentLoadCommand32 - Write a 32-bit segment load command.
|
||||
/// WriteSegmentLoadCommand - Write a 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 VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
uint64_t SectionDataSize) {
|
||||
// struct segment_command (56 bytes)
|
||||
void WriteSegmentLoadCommand(unsigned NumSections,
|
||||
uint64_t VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
uint64_t SectionDataSize) {
|
||||
// struct segment_command (56 bytes) or
|
||||
// struct segment_command_64 (72 bytes)
|
||||
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
|
||||
Write32(LCT_Segment);
|
||||
Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
|
||||
unsigned SegmentLoadCommandSize = Is64Bit ? SegmentLoadCommand64Size :
|
||||
SegmentLoadCommand32Size;
|
||||
Write32(Is64Bit ? LCT_Segment64 : LCT_Segment);
|
||||
Write32(SegmentLoadCommandSize +
|
||||
NumSections * (Is64Bit ? Section64Size : Section32Size));
|
||||
|
||||
WriteString("", 16);
|
||||
Write32(0); // vmaddr
|
||||
Write32(VMSize); // vmsize
|
||||
Write32(SectionDataStartOffset); // file offset
|
||||
Write32(SectionDataSize); // file size
|
||||
if (Is64Bit) {
|
||||
Write64(0); // vmaddr
|
||||
Write64(VMSize); // vmsize
|
||||
Write64(SectionDataStartOffset); // file offset
|
||||
Write64(SectionDataSize); // file size
|
||||
} else {
|
||||
Write32(0); // vmaddr
|
||||
Write32(VMSize); // vmsize
|
||||
Write32(SectionDataStartOffset); // file offset
|
||||
Write32(SectionDataSize); // file size
|
||||
}
|
||||
Write32(0x7); // maxprot
|
||||
Write32(0x7); // initprot
|
||||
Write32(NumSections);
|
||||
Write32(0); // flags
|
||||
|
||||
assert(OS.tell() - Start == SegmentLoadCommand32Size);
|
||||
assert(OS.tell() - Start == SegmentLoadCommandSize);
|
||||
}
|
||||
|
||||
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations) {
|
||||
void WriteSection(const MCSectionData &SD, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations) {
|
||||
// The offset is unused for virtual sections.
|
||||
if (isVirtualSection(SD.getSection())) {
|
||||
assert(SD.getFileSize() == 0 && "Invalid file size!");
|
||||
FileOffset = 0;
|
||||
}
|
||||
|
||||
// struct section (68 bytes)
|
||||
// struct section (68 bytes) or
|
||||
// struct section_64 (80 bytes)
|
||||
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
@@ -296,8 +319,13 @@ public:
|
||||
static_cast<const MCSectionMachO&>(SD.getSection());
|
||||
WriteString(Section.getSectionName(), 16);
|
||||
WriteString(Section.getSegmentName(), 16);
|
||||
Write32(SD.getAddress()); // address
|
||||
Write32(SD.getSize()); // size
|
||||
if (Is64Bit) {
|
||||
Write64(SD.getAddress()); // address
|
||||
Write64(SD.getSize()); // size
|
||||
} else {
|
||||
Write32(SD.getAddress()); // address
|
||||
Write32(SD.getSize()); // size
|
||||
}
|
||||
Write32(FileOffset);
|
||||
|
||||
unsigned Flags = Section.getTypeAndAttributes();
|
||||
@@ -311,8 +339,10 @@ public:
|
||||
Write32(Flags);
|
||||
Write32(0); // reserved1
|
||||
Write32(Section.getStubSize()); // reserved2
|
||||
if (Is64Bit)
|
||||
Write32(0); // reserved3
|
||||
|
||||
assert(OS.tell() - Start == Section32Size);
|
||||
assert(OS.tell() - Start == Is64Bit ? Section64Size : Section32Size);
|
||||
}
|
||||
|
||||
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
||||
@@ -748,7 +778,8 @@ public:
|
||||
// The section data starts after the header, the segment load command (and
|
||||
// section headers) and the symbol table.
|
||||
unsigned NumLoadCommands = 1;
|
||||
uint64_t LoadCommandsSize =
|
||||
uint64_t LoadCommandsSize = Is64Bit ?
|
||||
SegmentLoadCommand64Size + NumSections * Section64Size :
|
||||
SegmentLoadCommand32Size + NumSections * Section32Size;
|
||||
|
||||
// Add the symbol table load command sizes, if used.
|
||||
@@ -759,7 +790,8 @@ public:
|
||||
|
||||
// Compute the total size of the section data, as well as its file size and
|
||||
// vm size.
|
||||
uint64_t SectionDataStart = Header32Size + LoadCommandsSize;
|
||||
uint64_t SectionDataStart = (Is64Bit ? Header64Size : Header32Size)
|
||||
+ LoadCommandsSize;
|
||||
uint64_t SectionDataSize = 0;
|
||||
uint64_t SectionDataFileSize = 0;
|
||||
uint64_t VMSize = 0;
|
||||
@@ -785,10 +817,10 @@ public:
|
||||
SectionDataFileSize += SectionDataPadding;
|
||||
|
||||
// Write the prolog, starting with the header and load command...
|
||||
WriteHeader32(NumLoadCommands, LoadCommandsSize,
|
||||
Asm.getSubsectionsViaSymbols());
|
||||
WriteSegmentLoadCommand32(NumSections, VMSize,
|
||||
SectionDataStart, SectionDataSize);
|
||||
WriteHeader(NumLoadCommands, LoadCommandsSize,
|
||||
Asm.getSubsectionsViaSymbols());
|
||||
WriteSegmentLoadCommand(NumSections, VMSize,
|
||||
SectionDataStart, SectionDataSize);
|
||||
|
||||
// ... and then the section headers.
|
||||
//
|
||||
@@ -815,7 +847,7 @@ public:
|
||||
|
||||
unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
|
||||
uint64_t SectionStart = SectionDataStart + SD.getAddress();
|
||||
WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs);
|
||||
WriteSection(SD, SectionStart, RelocTableEnd, NumRelocs);
|
||||
RelocTableEnd += NumRelocs * RelocationInfoSize;
|
||||
}
|
||||
|
||||
@@ -1284,7 +1316,10 @@ void MCAssembler::Finish() {
|
||||
dump(); });
|
||||
|
||||
// Write the object file.
|
||||
MachObjectWriter MOW(OS);
|
||||
//
|
||||
// FIXME: Factor out MCObjectWriter.
|
||||
bool Is64Bit = StringRef(getBackend().getTarget().getName()) == "x86-64";
|
||||
MachObjectWriter MOW(OS, Is64Bit);
|
||||
MOW.WriteObject(*this);
|
||||
|
||||
OS.flush();
|
||||
|
Reference in New Issue
Block a user