llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-25 21:10:45 +00:00
|
|
|
#define DEBUG_TYPE "assembler"
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
#include "llvm/MC/MCAssembler.h"
|
2010-03-11 05:53:33 +00:00
|
|
|
#include "llvm/MC/MCAsmLayout.h"
|
2009-10-16 01:58:03 +00:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2009-08-22 19:19:12 +00:00
|
|
|
#include "llvm/MC/MCSectionMachO.h"
|
2009-10-16 01:58:03 +00:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
|
|
|
#include "llvm/MC/MCValue.h"
|
2009-08-22 11:41:10 +00:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2009-08-22 10:13:24 +00:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2009-08-25 21:10:45 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2010-02-13 09:28:03 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2009-08-22 10:13:24 +00:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2009-08-21 23:07:38 +00:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2009-08-21 18:29:01 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2010-02-02 19:38:14 +00:00
|
|
|
#include "llvm/Support/MachO.h"
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2010-02-13 09:28:03 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2010-03-13 22:10:17 +00:00
|
|
|
#include "llvm/Target/TargetRegistry.h"
|
2010-03-12 21:00:49 +00:00
|
|
|
#include "llvm/Target/TargetAsmBackend.h"
|
2010-02-13 09:29:02 +00:00
|
|
|
|
|
|
|
// FIXME: Gross.
|
|
|
|
#include "../Target/X86/X86FixupKinds.h"
|
|
|
|
|
2009-08-24 03:52:50 +00:00
|
|
|
#include <vector>
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
class MachObjectWriter;
|
|
|
|
|
2009-08-25 21:10:45 +00:00
|
|
|
STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
|
|
|
|
|
2009-08-28 07:08:35 +00:00
|
|
|
// FIXME FIXME FIXME: There are number of places in this file where we convert
|
|
|
|
// what is a 64-bit assembler value used for computation into a value in the
|
|
|
|
// object file, which may truncate it. We should detect that truncation where
|
|
|
|
// invalid and report errors back.
|
|
|
|
|
2010-03-19 09:28:55 +00:00
|
|
|
class MCObjectWriter;
|
2009-08-22 10:13:24 +00:00
|
|
|
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
|
2010-03-19 09:28:55 +00:00
|
|
|
MCObjectWriter *MOW);
|
2010-02-23 18:26:34 +00:00
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
/// isVirtualSection - Check if this is a section which does not actually exist
|
|
|
|
/// in the object file.
|
|
|
|
static bool isVirtualSection(const MCSection &Section) {
|
|
|
|
// FIXME: Lame.
|
|
|
|
const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
|
2010-03-15 21:56:38 +00:00
|
|
|
return (SMO.getType() == MCSectionMachO::S_ZEROFILL);
|
2009-08-28 05:49:21 +00:00
|
|
|
}
|
|
|
|
|
2010-02-17 14:52:22 +00:00
|
|
|
static unsigned getFixupKindLog2Size(unsigned Kind) {
|
2010-02-13 09:28:54 +00:00
|
|
|
switch (Kind) {
|
|
|
|
default: llvm_unreachable("invalid fixup kind!");
|
2010-02-13 09:29:02 +00:00
|
|
|
case X86::reloc_pcrel_1byte:
|
2010-02-13 09:28:54 +00:00
|
|
|
case FK_Data_1: return 0;
|
|
|
|
case FK_Data_2: return 1;
|
2010-02-13 09:29:02 +00:00
|
|
|
case X86::reloc_pcrel_4byte:
|
|
|
|
case X86::reloc_riprel_4byte:
|
2010-02-13 09:28:54 +00:00
|
|
|
case FK_Data_4: return 2;
|
|
|
|
case FK_Data_8: return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-17 14:52:22 +00:00
|
|
|
static bool isFixupKindPCRel(unsigned Kind) {
|
2010-02-13 09:45:59 +00:00
|
|
|
switch (Kind) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case X86::reloc_pcrel_1byte:
|
|
|
|
case X86::reloc_pcrel_4byte:
|
|
|
|
case X86::reloc_riprel_4byte:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-19 09:28:55 +00:00
|
|
|
class MCObjectWriter {
|
|
|
|
MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
|
|
|
|
void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
|
|
|
|
|
|
|
|
protected:
|
|
|
|
raw_ostream &OS;
|
|
|
|
|
|
|
|
unsigned IsLittleEndian : 1;
|
|
|
|
|
|
|
|
protected: // Can only create subclasses.
|
|
|
|
MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
|
|
|
|
: OS(_OS), IsLittleEndian(_IsLittleEndian) {}
|
|
|
|
virtual ~MCObjectWriter();
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
bool isLittleEndian() { return IsLittleEndian; }
|
|
|
|
|
|
|
|
raw_ostream &getStream() { return OS; }
|
|
|
|
|
|
|
|
/// @name Binary Output Methods
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
void Write8(uint8_t Value) {
|
|
|
|
OS << char(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE16(uint16_t Value) {
|
|
|
|
Write8(uint8_t(Value >> 0));
|
|
|
|
Write8(uint8_t(Value >> 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE32(uint32_t Value) {
|
|
|
|
WriteLE16(uint16_t(Value >> 0));
|
|
|
|
WriteLE16(uint16_t(Value >> 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE64(uint64_t Value) {
|
|
|
|
WriteLE32(uint32_t(Value >> 0));
|
|
|
|
WriteLE32(uint32_t(Value >> 32));
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE16(uint16_t Value) {
|
|
|
|
Write8(uint8_t(Value >> 8));
|
|
|
|
Write8(uint8_t(Value >> 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE32(uint32_t Value) {
|
|
|
|
WriteBE16(uint16_t(Value >> 16));
|
|
|
|
WriteBE16(uint16_t(Value >> 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE64(uint64_t Value) {
|
|
|
|
WriteBE32(uint32_t(Value >> 32));
|
|
|
|
WriteBE32(uint32_t(Value >> 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write16(uint16_t Value) {
|
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE16(Value);
|
|
|
|
else
|
|
|
|
WriteBE16(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write32(uint32_t Value) {
|
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE32(Value);
|
|
|
|
else
|
|
|
|
WriteBE32(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write64(uint64_t Value) {
|
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE64(Value);
|
|
|
|
else
|
|
|
|
WriteBE64(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteZeros(unsigned N) {
|
|
|
|
const char Zeros[16] = { 0 };
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
|
|
|
OS << StringRef(Zeros, 16);
|
|
|
|
|
|
|
|
OS << StringRef(Zeros, N % 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
|
|
|
OS << Str;
|
|
|
|
if (ZeroFillSize)
|
|
|
|
WriteZeros(ZeroFillSize - Str.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
};
|
|
|
|
|
|
|
|
MCObjectWriter::~MCObjectWriter() {
|
|
|
|
}
|
|
|
|
|
|
|
|
class MachObjectWriter : public MCObjectWriter {
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
// See <mach-o/loader.h>.
|
|
|
|
enum {
|
|
|
|
Header_Magic32 = 0xFEEDFACE,
|
|
|
|
Header_Magic64 = 0xFEEDFACF
|
|
|
|
};
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
enum {
|
|
|
|
Header32Size = 28,
|
|
|
|
Header64Size = 32,
|
|
|
|
SegmentLoadCommand32Size = 56,
|
|
|
|
SegmentLoadCommand64Size = 72,
|
|
|
|
Section32Size = 68,
|
|
|
|
Section64Size = 80,
|
|
|
|
SymtabLoadCommandSize = 24,
|
|
|
|
DysymtabLoadCommandSize = 80,
|
|
|
|
Nlist32Size = 12,
|
|
|
|
Nlist64Size = 16,
|
|
|
|
RelocationInfoSize = 8
|
|
|
|
};
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
enum HeaderFileType {
|
|
|
|
HFT_Object = 0x1
|
|
|
|
};
|
|
|
|
|
2009-08-26 21:22:22 +00:00
|
|
|
enum HeaderFlags {
|
|
|
|
HF_SubsectionsViaSymbols = 0x2000
|
|
|
|
};
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
enum LoadCommandType {
|
2009-08-22 10:13:24 +00:00
|
|
|
LCT_Segment = 0x1,
|
|
|
|
LCT_Symtab = 0x2,
|
2010-03-13 22:10:17 +00:00
|
|
|
LCT_Dysymtab = 0xb,
|
|
|
|
LCT_Segment64 = 0x19
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
};
|
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
// See <mach-o/nlist.h>.
|
|
|
|
enum SymbolTypeType {
|
|
|
|
STT_Undefined = 0x00,
|
|
|
|
STT_Absolute = 0x02,
|
|
|
|
STT_Section = 0x0e
|
|
|
|
};
|
|
|
|
|
|
|
|
enum SymbolTypeFlags {
|
|
|
|
// If any of these bits are set, then the entry is a stab entry number (see
|
|
|
|
// <mach-o/stab.h>. Otherwise the other masks apply.
|
|
|
|
STF_StabsEntryMask = 0xe0,
|
|
|
|
|
|
|
|
STF_TypeMask = 0x0e,
|
|
|
|
STF_External = 0x01,
|
|
|
|
STF_PrivateExtern = 0x10
|
|
|
|
};
|
|
|
|
|
2009-08-26 00:18:21 +00:00
|
|
|
/// IndirectSymbolFlags - Flags for encoding special values in the indirect
|
|
|
|
/// symbol entry.
|
|
|
|
enum IndirectSymbolFlags {
|
|
|
|
ISF_Local = 0x80000000,
|
|
|
|
ISF_Absolute = 0x40000000
|
|
|
|
};
|
|
|
|
|
2009-08-26 13:58:10 +00:00
|
|
|
/// 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
|
|
|
|
};
|
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
/// MachSymbolData - Helper struct for containing some precomputed information
|
|
|
|
/// on symbols.
|
|
|
|
struct MachSymbolData {
|
|
|
|
MCSymbolData *SymbolData;
|
|
|
|
uint64_t StringIndex;
|
|
|
|
uint8_t SectionIndex;
|
|
|
|
|
|
|
|
// Support lexicographic sorting.
|
|
|
|
bool operator<(const MachSymbolData &RHS) const {
|
|
|
|
const std::string &Name = SymbolData->getSymbol().getName();
|
|
|
|
return Name < RHS.SymbolData->getSymbol().getName();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
unsigned Is64Bit : 1;
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2010-03-19 07:09:18 +00:00
|
|
|
/// @name Relocation Data
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
struct MachRelocationEntry {
|
|
|
|
uint32_t Word0;
|
|
|
|
uint32_t Word1;
|
|
|
|
};
|
|
|
|
|
|
|
|
llvm::DenseMap<const MCSectionData*,
|
|
|
|
std::vector<MachRelocationEntry> > Relocations;
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
/// @name Symbol Table Data
|
|
|
|
|
|
|
|
SmallString<256> StringTable;
|
|
|
|
std::vector<MachSymbolData> LocalSymbolData;
|
|
|
|
std::vector<MachSymbolData> ExternalSymbolData;
|
|
|
|
std::vector<MachSymbolData> UndefinedSymbolData;
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
public:
|
2010-03-19 09:28:55 +00:00
|
|
|
MachObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool _IsLittleEndian = true)
|
|
|
|
: MCObjectWriter(_OS, _IsLittleEndian), Is64Bit(_Is64Bit) {
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
|
|
|
bool SubsectionsViaSymbols) {
|
2009-08-26 21:22:22 +00:00
|
|
|
uint32_t Flags = 0;
|
|
|
|
|
|
|
|
if (SubsectionsViaSymbols)
|
|
|
|
Flags |= HF_SubsectionsViaSymbols;
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
// struct mach_header (28 bytes) or
|
|
|
|
// struct mach_header_64 (32 bytes)
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
Write32(Is64Bit ? Header_Magic64 : Header_Magic32);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
// FIXME: Support cputype.
|
2010-03-13 22:10:17 +00:00
|
|
|
Write32(Is64Bit ? MachO::CPUTypeX86_64 : MachO::CPUTypeI386);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
// FIXME: Support cpusubtype.
|
2010-02-02 19:38:14 +00:00
|
|
|
Write32(MachO::CPUSubType_I386_ALL);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
Write32(HFT_Object);
|
2009-08-26 21:22:22 +00:00
|
|
|
Write32(NumLoadCommands); // Object files have a single load command, the
|
|
|
|
// segment.
|
2009-08-22 10:13:24 +00:00
|
|
|
Write32(LoadCommandsSize);
|
2009-08-26 21:22:22 +00:00
|
|
|
Write32(Flags);
|
2010-03-13 22:10:17 +00:00
|
|
|
if (Is64Bit)
|
|
|
|
Write32(0); // reserved
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
assert(OS.tell() - Start == Is64Bit ? Header64Size : Header32Size);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
/// WriteSegmentLoadCommand - Write a segment load command.
|
2009-08-21 18:29:01 +00:00
|
|
|
///
|
|
|
|
/// \arg NumSections - The number of sections in this segment.
|
|
|
|
/// \arg SectionDataSize - The total size of the sections.
|
2010-03-13 22:10:17 +00:00
|
|
|
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)
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
unsigned SegmentLoadCommandSize = Is64Bit ? SegmentLoadCommand64Size :
|
|
|
|
SegmentLoadCommand32Size;
|
|
|
|
Write32(Is64Bit ? LCT_Segment64 : LCT_Segment);
|
|
|
|
Write32(SegmentLoadCommandSize +
|
|
|
|
NumSections * (Is64Bit ? Section64Size : Section32Size));
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2010-03-19 09:28:55 +00:00
|
|
|
WriteBytes("", 16);
|
2010-03-13 22:10:17 +00:00
|
|
|
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
|
|
|
|
}
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
Write32(0x7); // maxprot
|
|
|
|
Write32(0x7); // initprot
|
|
|
|
Write32(NumSections);
|
|
|
|
Write32(0); // flags
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
assert(OS.tell() - Start == SegmentLoadCommandSize);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
void WriteSection(const MCSectionData &SD, uint64_t FileOffset,
|
|
|
|
uint64_t RelocationsStart, unsigned NumRelocations) {
|
2009-08-28 05:49:21 +00:00
|
|
|
// The offset is unused for virtual sections.
|
|
|
|
if (isVirtualSection(SD.getSection())) {
|
|
|
|
assert(SD.getFileSize() == 0 && "Invalid file size!");
|
|
|
|
FileOffset = 0;
|
|
|
|
}
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
// struct section (68 bytes) or
|
|
|
|
// struct section_64 (80 bytes)
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
// FIXME: cast<> support!
|
|
|
|
const MCSectionMachO &Section =
|
|
|
|
static_cast<const MCSectionMachO&>(SD.getSection());
|
2010-03-19 09:28:55 +00:00
|
|
|
WriteBytes(Section.getSectionName(), 16);
|
|
|
|
WriteBytes(Section.getSegmentName(), 16);
|
2010-03-13 22:10:17 +00:00
|
|
|
if (Is64Bit) {
|
|
|
|
Write64(SD.getAddress()); // address
|
|
|
|
Write64(SD.getSize()); // size
|
|
|
|
} else {
|
|
|
|
Write32(SD.getAddress()); // address
|
|
|
|
Write32(SD.getSize()); // size
|
|
|
|
}
|
2009-08-22 08:28:27 +00:00
|
|
|
Write32(FileOffset);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2010-02-02 21:44:01 +00:00
|
|
|
unsigned Flags = Section.getTypeAndAttributes();
|
|
|
|
if (SD.hasInstructions())
|
|
|
|
Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS;
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
|
|
|
|
Write32(Log2_32(SD.getAlignment()));
|
2009-08-26 13:58:10 +00:00
|
|
|
Write32(NumRelocations ? RelocationsStart : 0);
|
|
|
|
Write32(NumRelocations);
|
2010-02-02 21:44:01 +00:00
|
|
|
Write32(Flags);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
Write32(0); // reserved1
|
|
|
|
Write32(Section.getStubSize()); // reserved2
|
2010-03-13 22:10:17 +00:00
|
|
|
if (Is64Bit)
|
|
|
|
Write32(0); // reserved3
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
assert(OS.tell() - Start == Is64Bit ? Section64Size : Section32Size);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
}
|
2009-08-22 08:28:27 +00:00
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
|
|
|
uint32_t StringTableOffset,
|
|
|
|
uint32_t StringTableSize) {
|
|
|
|
// struct symtab_command (24 bytes)
|
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
Write32(LCT_Symtab);
|
|
|
|
Write32(SymtabLoadCommandSize);
|
|
|
|
Write32(SymbolOffset);
|
|
|
|
Write32(NumSymbols);
|
|
|
|
Write32(StringTableOffset);
|
|
|
|
Write32(StringTableSize);
|
|
|
|
|
|
|
|
assert(OS.tell() - Start == SymtabLoadCommandSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
// struct dysymtab_command (80 bytes)
|
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
Write32(LCT_Dysymtab);
|
|
|
|
Write32(DysymtabLoadCommandSize);
|
|
|
|
Write32(FirstLocalSymbol);
|
|
|
|
Write32(NumLocalSymbols);
|
|
|
|
Write32(FirstExternalSymbol);
|
|
|
|
Write32(NumExternalSymbols);
|
|
|
|
Write32(FirstUndefinedSymbol);
|
|
|
|
Write32(NumUndefinedSymbols);
|
|
|
|
Write32(0); // tocoff
|
|
|
|
Write32(0); // ntoc
|
|
|
|
Write32(0); // modtaboff
|
|
|
|
Write32(0); // nmodtab
|
|
|
|
Write32(0); // extrefsymoff
|
|
|
|
Write32(0); // nextrefsyms
|
|
|
|
Write32(IndirectSymbolOffset);
|
|
|
|
Write32(NumIndirectSymbols);
|
|
|
|
Write32(0); // extreloff
|
|
|
|
Write32(0); // nextrel
|
|
|
|
Write32(0); // locreloff
|
|
|
|
Write32(0); // nlocrel
|
|
|
|
|
|
|
|
assert(OS.tell() - Start == DysymtabLoadCommandSize);
|
|
|
|
}
|
|
|
|
|
2010-03-13 22:49:35 +00:00
|
|
|
void WriteNlist(MachSymbolData &MSD) {
|
2009-08-26 02:48:04 +00:00
|
|
|
MCSymbolData &Data = *MSD.SymbolData;
|
2009-08-31 08:08:06 +00:00
|
|
|
const MCSymbol &Symbol = Data.getSymbol();
|
2009-08-22 11:41:10 +00:00
|
|
|
uint8_t Type = 0;
|
2009-08-28 07:08:35 +00:00
|
|
|
uint16_t Flags = Data.getFlags();
|
|
|
|
uint32_t Address = 0;
|
2009-08-22 11:41:10 +00:00
|
|
|
|
|
|
|
// Set the N_TYPE bits. See <mach-o/nlist.h>.
|
|
|
|
//
|
|
|
|
// FIXME: Are the prebound or indirect fields possible here?
|
|
|
|
if (Symbol.isUndefined())
|
|
|
|
Type = STT_Undefined;
|
|
|
|
else if (Symbol.isAbsolute())
|
|
|
|
Type = STT_Absolute;
|
|
|
|
else
|
|
|
|
Type = STT_Section;
|
|
|
|
|
|
|
|
// FIXME: Set STAB bits.
|
|
|
|
|
2009-08-26 02:48:04 +00:00
|
|
|
if (Data.isPrivateExtern())
|
2009-08-24 08:40:12 +00:00
|
|
|
Type |= STF_PrivateExtern;
|
2009-08-22 11:41:10 +00:00
|
|
|
|
|
|
|
// Set external bit.
|
2009-08-26 02:48:04 +00:00
|
|
|
if (Data.isExternal() || Symbol.isUndefined())
|
2009-08-22 11:41:10 +00:00
|
|
|
Type |= STF_External;
|
|
|
|
|
2009-08-28 07:08:35 +00:00
|
|
|
// Compute the symbol address.
|
|
|
|
if (Symbol.isDefined()) {
|
|
|
|
if (Symbol.isAbsolute()) {
|
|
|
|
llvm_unreachable("FIXME: Not yet implemented!");
|
|
|
|
} else {
|
2010-03-11 18:22:51 +00:00
|
|
|
Address = Data.getAddress();
|
2009-08-28 07:08:35 +00:00
|
|
|
}
|
|
|
|
} else if (Data.isCommon()) {
|
|
|
|
// Common symbols are encoded with the size in the address
|
|
|
|
// field, and their alignment in the flags.
|
|
|
|
Address = Data.getCommonSize();
|
|
|
|
|
|
|
|
// Common alignment is packed into the 'desc' bits.
|
|
|
|
if (unsigned Align = Data.getCommonAlignment()) {
|
|
|
|
unsigned Log2Size = Log2_32(Align);
|
|
|
|
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
|
|
|
|
if (Log2Size > 15)
|
|
|
|
llvm_report_error("invalid 'common' alignment '" +
|
|
|
|
Twine(Align) + "'");
|
|
|
|
// FIXME: Keep this mask with the SymbolFlags enumeration.
|
|
|
|
Flags = (Flags & 0xF0FF) | (Log2Size << 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// struct nlist (12 bytes)
|
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
Write32(MSD.StringIndex);
|
2009-08-22 10:13:24 +00:00
|
|
|
Write8(Type);
|
2009-08-22 11:41:10 +00:00
|
|
|
Write8(MSD.SectionIndex);
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-24 08:40:12 +00:00
|
|
|
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
|
|
|
|
// value.
|
2009-08-28 07:08:35 +00:00
|
|
|
Write16(Flags);
|
2010-03-13 22:49:35 +00:00
|
|
|
if (Is64Bit)
|
|
|
|
Write64(Address);
|
|
|
|
else
|
|
|
|
Write32(Address);
|
2009-08-22 10:13:24 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 07:09:18 +00:00
|
|
|
void RecordScatteredRelocation(MCAssembler &Asm, MCFragment &Fragment,
|
|
|
|
const MCAsmFixup &Fixup, MCValue Target,
|
|
|
|
uint64_t &FixedValue) {
|
2010-02-11 21:29:46 +00:00
|
|
|
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
|
2010-03-09 21:27:30 +00:00
|
|
|
unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
2010-02-17 23:45:16 +00:00
|
|
|
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
2009-08-26 13:58:10 +00:00
|
|
|
unsigned Type = RIT_Vanilla;
|
|
|
|
|
|
|
|
// See <reloc.h>.
|
2010-03-18 00:59:10 +00:00
|
|
|
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
2010-03-10 20:58:31 +00:00
|
|
|
MCSymbolData *A_SD = &Asm.getSymbolData(*A);
|
2010-03-08 21:10:39 +00:00
|
|
|
|
2010-03-10 00:58:25 +00:00
|
|
|
if (!A_SD->getFragment())
|
2010-03-08 21:10:39 +00:00
|
|
|
llvm_report_error("symbol '" + A->getName() +
|
|
|
|
"' can not be undefined in a subtraction expression");
|
|
|
|
|
2010-03-11 18:22:51 +00:00
|
|
|
uint32_t Value = A_SD->getAddress();
|
2009-08-26 13:58:10 +00:00
|
|
|
uint32_t Value2 = 0;
|
|
|
|
|
2010-03-18 00:59:10 +00:00
|
|
|
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
|
|
|
MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
|
2010-03-08 21:10:39 +00:00
|
|
|
|
2010-03-10 00:58:25 +00:00
|
|
|
if (!B_SD->getFragment())
|
2010-03-18 00:59:10 +00:00
|
|
|
llvm_report_error("symbol '" + B->getSymbol().getName() +
|
2010-03-08 21:10:39 +00:00
|
|
|
"' can not be undefined in a subtraction expression");
|
|
|
|
|
2010-03-10 02:10:29 +00:00
|
|
|
// 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'.
|
2010-03-10 00:58:25 +00:00
|
|
|
Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference;
|
2010-03-11 18:22:51 +00:00
|
|
|
Value2 = B_SD->getAddress();
|
2009-08-26 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 07:09:18 +00:00
|
|
|
// Relocations are written out in reverse order, so the PAIR comes first.
|
2010-03-10 00:58:25 +00:00
|
|
|
if (Type == RIT_Difference || Type == RIT_LocalDifference) {
|
2009-08-26 13:58:10 +00:00
|
|
|
MachRelocationEntry MRE;
|
|
|
|
MRE.Word0 = ((0 << 0) |
|
2010-03-09 21:27:47 +00:00
|
|
|
(RIT_Pair << 24) |
|
2009-08-26 13:58:10 +00:00
|
|
|
(Log2Size << 28) |
|
2010-03-09 21:27:47 +00:00
|
|
|
(IsPCRel << 30) |
|
2009-08-26 13:58:10 +00:00
|
|
|
RF_Scattered);
|
|
|
|
MRE.Word1 = Value2;
|
2010-03-19 07:09:18 +00:00
|
|
|
Relocations[Fragment.getParent()].push_back(MRE);
|
2009-08-26 13:58:10 +00:00
|
|
|
}
|
2010-03-19 07:09:18 +00:00
|
|
|
|
|
|
|
MachRelocationEntry MRE;
|
|
|
|
MRE.Word0 = ((Address << 0) |
|
|
|
|
(Type << 24) |
|
|
|
|
(Log2Size << 28) |
|
|
|
|
(IsPCRel << 30) |
|
|
|
|
RF_Scattered);
|
|
|
|
MRE.Word1 = Value;
|
|
|
|
Relocations[Fragment.getParent()].push_back(MRE);
|
2009-08-26 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 07:09:18 +00:00
|
|
|
void RecordRelocation(MCAssembler &Asm, MCDataFragment &Fragment,
|
|
|
|
const MCAsmFixup &Fixup, MCValue Target,
|
|
|
|
uint64_t &FixedValue) {
|
2010-03-09 21:27:58 +00:00
|
|
|
unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
|
|
|
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
|
|
|
|
|
|
|
// If this is a difference or a defined symbol plus an offset, then we need
|
|
|
|
// a scattered relocation entry.
|
|
|
|
uint32_t Offset = Target.getConstant();
|
|
|
|
if (IsPCRel)
|
|
|
|
Offset += 1 << Log2Size;
|
2009-10-16 01:58:03 +00:00
|
|
|
if (Target.getSymB() ||
|
2010-03-18 00:59:10 +00:00
|
|
|
(Target.getSymA() && !Target.getSymA()->getSymbol().isUndefined() &&
|
2010-03-19 07:09:18 +00:00
|
|
|
Offset)) {
|
|
|
|
RecordScatteredRelocation(Asm, Fragment, Fixup, Target, FixedValue);
|
|
|
|
return;
|
|
|
|
}
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-26 13:58:10 +00:00
|
|
|
// See <reloc.h>.
|
2010-02-11 21:29:46 +00:00
|
|
|
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
|
2009-08-26 13:58:10 +00:00
|
|
|
uint32_t Value = 0;
|
|
|
|
unsigned Index = 0;
|
|
|
|
unsigned IsExtern = 0;
|
|
|
|
unsigned Type = 0;
|
|
|
|
|
2009-10-16 01:58:03 +00:00
|
|
|
if (Target.isAbsolute()) { // constant
|
2009-08-26 13:58:10 +00:00
|
|
|
// SymbolNum of 0 indicates the absolute section.
|
2010-02-13 09:28:15 +00:00
|
|
|
//
|
2010-03-11 05:53:37 +00:00
|
|
|
// FIXME: Currently, these are never generated (see code below). I cannot
|
|
|
|
// find a case where they are actually emitted.
|
2009-08-26 13:58:10 +00:00
|
|
|
Type = RIT_Vanilla;
|
|
|
|
Value = 0;
|
|
|
|
} else {
|
2010-03-18 00:59:10 +00:00
|
|
|
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
|
2010-03-10 20:58:31 +00:00
|
|
|
MCSymbolData *SD = &Asm.getSymbolData(*Symbol);
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-26 13:58:10 +00:00
|
|
|
if (Symbol->isUndefined()) {
|
|
|
|
IsExtern = 1;
|
|
|
|
Index = SD->getIndex();
|
|
|
|
Value = 0;
|
|
|
|
} else {
|
|
|
|
// The index is the section ordinal.
|
|
|
|
//
|
|
|
|
// FIXME: O(N)
|
|
|
|
Index = 1;
|
2010-02-13 09:45:59 +00:00
|
|
|
MCAssembler::iterator it = Asm.begin(), ie = Asm.end();
|
|
|
|
for (; it != ie; ++it, ++Index)
|
2009-08-26 13:58:10 +00:00
|
|
|
if (&*it == SD->getFragment()->getParent())
|
|
|
|
break;
|
2010-02-13 09:45:59 +00:00
|
|
|
assert(it != ie && "Unable to find section index!");
|
2010-03-11 18:22:51 +00:00
|
|
|
Value = SD->getAddress();
|
2009-08-26 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Type = RIT_Vanilla;
|
|
|
|
}
|
|
|
|
|
|
|
|
// struct relocation_info (8 bytes)
|
|
|
|
MachRelocationEntry MRE;
|
|
|
|
MRE.Word0 = Address;
|
|
|
|
MRE.Word1 = ((Index << 0) |
|
|
|
|
(IsPCRel << 24) |
|
|
|
|
(Log2Size << 25) |
|
|
|
|
(IsExtern << 27) |
|
|
|
|
(Type << 28));
|
2010-03-19 07:09:18 +00:00
|
|
|
Relocations[Fragment.getParent()].push_back(MRE);
|
|
|
|
}
|
|
|
|
|
2010-03-10 20:58:31 +00:00
|
|
|
void BindIndirectSymbols(MCAssembler &Asm) {
|
2009-08-24 11:56:58 +00:00
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// FIXME: Revisit this when the dust settles.
|
|
|
|
|
|
|
|
// Bind non lazy symbol pointers first.
|
|
|
|
for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
|
|
|
|
ie = Asm.indirect_symbol_end(); it != ie; ++it) {
|
|
|
|
// FIXME: cast<> support!
|
|
|
|
const MCSectionMachO &Section =
|
|
|
|
static_cast<const MCSectionMachO&>(it->SectionData->getSection());
|
|
|
|
|
2010-03-15 21:56:38 +00:00
|
|
|
if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
|
2009-08-24 11:56:58 +00:00
|
|
|
continue;
|
|
|
|
|
2010-03-10 20:58:31 +00:00
|
|
|
Asm.getOrCreateSymbolData(*it->Symbol);
|
2009-08-24 11:56:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Then lazy symbol pointers and symbol stubs.
|
|
|
|
for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
|
|
|
|
ie = Asm.indirect_symbol_end(); it != ie; ++it) {
|
|
|
|
// FIXME: cast<> support!
|
|
|
|
const MCSectionMachO &Section =
|
|
|
|
static_cast<const MCSectionMachO&>(it->SectionData->getSection());
|
|
|
|
|
2010-03-15 21:56:38 +00:00
|
|
|
if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
|
|
|
|
Section.getType() != MCSectionMachO::S_SYMBOL_STUBS)
|
2009-08-24 11:56:58 +00:00
|
|
|
continue;
|
|
|
|
|
2010-03-10 20:58:31 +00:00
|
|
|
// Set the symbol type to undefined lazy, but only on construction.
|
|
|
|
//
|
|
|
|
// FIXME: Do not hardcode.
|
|
|
|
bool Created;
|
|
|
|
MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created);
|
|
|
|
if (Created)
|
|
|
|
Entry.setFlags(Entry.getFlags() | 0x0001);
|
2009-08-24 11:56:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
/// ComputeSymbolTable - Compute the symbol table data
|
2009-08-22 10:13:24 +00:00
|
|
|
///
|
|
|
|
/// \param StringTable [out] - The string table data.
|
|
|
|
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
|
|
|
/// string table.
|
2009-08-22 11:41:10 +00:00
|
|
|
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
|
|
|
std::vector<MachSymbolData> &LocalSymbolData,
|
|
|
|
std::vector<MachSymbolData> &ExternalSymbolData,
|
|
|
|
std::vector<MachSymbolData> &UndefinedSymbolData) {
|
|
|
|
// Build section lookup table.
|
|
|
|
DenseMap<const MCSection*, uint8_t> SectionIndexMap;
|
|
|
|
unsigned Index = 1;
|
|
|
|
for (MCAssembler::iterator it = Asm.begin(),
|
|
|
|
ie = Asm.end(); it != ie; ++it, ++Index)
|
|
|
|
SectionIndexMap[&it->getSection()] = Index;
|
|
|
|
assert(Index <= 256 && "Too many sections!");
|
2009-08-22 10:13:24 +00:00
|
|
|
|
|
|
|
// Index 0 is always the empty string.
|
2009-08-22 11:41:10 +00:00
|
|
|
StringMap<uint64_t> StringIndexMap;
|
2009-08-22 10:13:24 +00:00
|
|
|
StringTable += '\x00';
|
2009-08-22 11:41:10 +00:00
|
|
|
|
|
|
|
// Build the symbol arrays and the string table, but only for non-local
|
|
|
|
// symbols.
|
|
|
|
//
|
|
|
|
// The particular order that we collect the symbols and create the string
|
|
|
|
// table, then sort the symbols is chosen to match 'as'. Even though it
|
|
|
|
// doesn't matter for correctness, this is important for letting us diff .o
|
|
|
|
// files.
|
2009-08-22 10:13:24 +00:00
|
|
|
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
|
|
|
|
ie = Asm.symbol_end(); it != ie; ++it) {
|
2009-08-31 08:08:06 +00:00
|
|
|
const MCSymbol &Symbol = it->getSymbol();
|
2009-08-22 11:41:10 +00:00
|
|
|
|
2010-03-19 03:18:09 +00:00
|
|
|
// Ignore non-linker visible symbols.
|
|
|
|
if (!Asm.isSymbolLinkerVisible(it))
|
2009-08-26 22:13:22 +00:00
|
|
|
continue;
|
|
|
|
|
2009-08-24 08:39:57 +00:00
|
|
|
if (!it->isExternal() && !Symbol.isUndefined())
|
2009-08-22 11:41:10 +00:00
|
|
|
continue;
|
2009-08-22 10:13:24 +00:00
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
2009-08-22 10:13:24 +00:00
|
|
|
if (!Entry) {
|
|
|
|
Entry = StringTable.size();
|
2009-08-22 11:41:10 +00:00
|
|
|
StringTable += Symbol.getName();
|
2009-08-22 10:13:24 +00:00
|
|
|
StringTable += '\x00';
|
|
|
|
}
|
2009-08-22 11:41:10 +00:00
|
|
|
|
|
|
|
MachSymbolData MSD;
|
|
|
|
MSD.SymbolData = it;
|
|
|
|
MSD.StringIndex = Entry;
|
|
|
|
|
|
|
|
if (Symbol.isUndefined()) {
|
|
|
|
MSD.SectionIndex = 0;
|
|
|
|
UndefinedSymbolData.push_back(MSD);
|
|
|
|
} else if (Symbol.isAbsolute()) {
|
|
|
|
MSD.SectionIndex = 0;
|
|
|
|
ExternalSymbolData.push_back(MSD);
|
|
|
|
} else {
|
|
|
|
MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
|
|
|
|
assert(MSD.SectionIndex && "Invalid section index!");
|
|
|
|
ExternalSymbolData.push_back(MSD);
|
|
|
|
}
|
2009-08-22 10:13:24 +00:00
|
|
|
}
|
|
|
|
|
2009-08-22 11:41:10 +00:00
|
|
|
// Now add the data for local symbols.
|
|
|
|
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
|
|
|
|
ie = Asm.symbol_end(); it != ie; ++it) {
|
2009-08-31 08:08:06 +00:00
|
|
|
const MCSymbol &Symbol = it->getSymbol();
|
2009-08-22 11:41:10 +00:00
|
|
|
|
2010-03-19 03:18:09 +00:00
|
|
|
// Ignore non-linker visible symbols.
|
|
|
|
if (!Asm.isSymbolLinkerVisible(it))
|
2009-08-26 22:13:22 +00:00
|
|
|
continue;
|
|
|
|
|
2009-08-24 08:39:57 +00:00
|
|
|
if (it->isExternal() || Symbol.isUndefined())
|
2009-08-22 11:41:10 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
uint64_t &Entry = StringIndexMap[Symbol.getName()];
|
|
|
|
if (!Entry) {
|
|
|
|
Entry = StringTable.size();
|
|
|
|
StringTable += Symbol.getName();
|
|
|
|
StringTable += '\x00';
|
|
|
|
}
|
|
|
|
|
|
|
|
MachSymbolData MSD;
|
|
|
|
MSD.SymbolData = it;
|
|
|
|
MSD.StringIndex = Entry;
|
|
|
|
|
|
|
|
if (Symbol.isAbsolute()) {
|
|
|
|
MSD.SectionIndex = 0;
|
|
|
|
LocalSymbolData.push_back(MSD);
|
|
|
|
} else {
|
|
|
|
MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
|
|
|
|
assert(MSD.SectionIndex && "Invalid section index!");
|
|
|
|
LocalSymbolData.push_back(MSD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// External and undefined symbols are required to be in lexicographic order.
|
|
|
|
std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
|
|
|
|
std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
|
|
|
|
|
2009-08-26 13:57:54 +00:00
|
|
|
// Set the symbol indices.
|
|
|
|
Index = 0;
|
|
|
|
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
|
|
|
|
LocalSymbolData[i].SymbolData->setIndex(Index++);
|
|
|
|
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
|
|
|
|
ExternalSymbolData[i].SymbolData->setIndex(Index++);
|
|
|
|
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
|
|
|
|
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
|
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// The string table is padded to a multiple of 4.
|
|
|
|
while (StringTable.size() % 4)
|
|
|
|
StringTable += '\x00';
|
|
|
|
}
|
|
|
|
|
2010-03-19 07:09:33 +00:00
|
|
|
void ExecutePostLayoutBinding(MCAssembler &Asm) {
|
2009-08-26 00:18:21 +00:00
|
|
|
// Create symbol data for any indirect symbols.
|
2010-03-10 20:58:31 +00:00
|
|
|
BindIndirectSymbols(Asm);
|
2009-08-24 11:56:58 +00:00
|
|
|
|
2010-03-19 07:09:33 +00:00
|
|
|
// Compute symbol table information and bind symbol indices.
|
|
|
|
ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
|
|
|
|
UndefinedSymbolData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteObject(const MCAssembler &Asm) {
|
|
|
|
unsigned NumSections = Asm.size();
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// The section data starts after the header, the segment load command (and
|
|
|
|
// section headers) and the symbol table.
|
|
|
|
unsigned NumLoadCommands = 1;
|
2010-03-13 22:10:17 +00:00
|
|
|
uint64_t LoadCommandsSize = Is64Bit ?
|
|
|
|
SegmentLoadCommand64Size + NumSections * Section64Size :
|
2009-08-22 10:13:24 +00:00
|
|
|
SegmentLoadCommand32Size + NumSections * Section32Size;
|
|
|
|
|
|
|
|
// Add the symbol table load command sizes, if used.
|
2010-03-19 07:09:33 +00:00
|
|
|
unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
|
|
|
|
UndefinedSymbolData.size();
|
2009-08-22 10:13:24 +00:00
|
|
|
if (NumSymbols) {
|
|
|
|
NumLoadCommands += 2;
|
|
|
|
LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
|
|
|
|
}
|
|
|
|
|
2009-08-28 05:49:04 +00:00
|
|
|
// Compute the total size of the section data, as well as its file size and
|
|
|
|
// vm size.
|
2010-03-13 22:10:17 +00:00
|
|
|
uint64_t SectionDataStart = (Is64Bit ? Header64Size : Header32Size)
|
|
|
|
+ LoadCommandsSize;
|
2009-08-22 08:28:27 +00:00
|
|
|
uint64_t SectionDataSize = 0;
|
2009-08-28 05:49:04 +00:00
|
|
|
uint64_t SectionDataFileSize = 0;
|
|
|
|
uint64_t VMSize = 0;
|
2010-03-19 07:09:33 +00:00
|
|
|
for (MCAssembler::const_iterator it = Asm.begin(),
|
2009-08-28 05:49:04 +00:00
|
|
|
ie = Asm.end(); it != ie; ++it) {
|
2010-03-19 07:09:33 +00:00
|
|
|
const MCSectionData &SD = *it;
|
2009-08-28 05:49:04 +00:00
|
|
|
|
|
|
|
VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
|
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
if (isVirtualSection(SD.getSection()))
|
|
|
|
continue;
|
|
|
|
|
2009-08-28 05:49:04 +00:00
|
|
|
SectionDataSize = std::max(SectionDataSize,
|
|
|
|
SD.getAddress() + SD.getSize());
|
2009-10-16 01:58:15 +00:00
|
|
|
SectionDataFileSize = std::max(SectionDataFileSize,
|
2009-08-28 05:49:04 +00:00
|
|
|
SD.getAddress() + SD.getFileSize());
|
2009-08-22 08:28:27 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 23:00:14 +00:00
|
|
|
// The section data is padded to 4 bytes.
|
2009-08-28 05:49:04 +00:00
|
|
|
//
|
|
|
|
// FIXME: Is this machine dependent?
|
|
|
|
unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
|
|
|
|
SectionDataFileSize += SectionDataPadding;
|
|
|
|
|
2009-08-22 08:28:27 +00:00
|
|
|
// Write the prolog, starting with the header and load command...
|
2010-03-13 22:10:17 +00:00
|
|
|
WriteHeader(NumLoadCommands, LoadCommandsSize,
|
|
|
|
Asm.getSubsectionsViaSymbols());
|
|
|
|
WriteSegmentLoadCommand(NumSections, VMSize,
|
|
|
|
SectionDataStart, SectionDataSize);
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2010-03-19 07:09:18 +00:00
|
|
|
// ... and then the section headers.
|
|
|
|
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
|
2010-03-19 07:09:33 +00:00
|
|
|
for (MCAssembler::const_iterator it = Asm.begin(),
|
2010-03-19 07:09:18 +00:00
|
|
|
ie = Asm.end(); it != ie; ++it) {
|
|
|
|
std::vector<MachRelocationEntry> &Relocs = Relocations[it];
|
|
|
|
unsigned NumRelocs = Relocs.size();
|
|
|
|
uint64_t SectionStart = SectionDataStart + it->getAddress();
|
|
|
|
WriteSection(*it, SectionStart, RelocTableEnd, NumRelocs);
|
2009-08-26 13:58:10 +00:00
|
|
|
RelocTableEnd += NumRelocs * RelocationInfoSize;
|
|
|
|
}
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// Write the symbol table load command, if used.
|
|
|
|
if (NumSymbols) {
|
|
|
|
unsigned FirstLocalSymbol = 0;
|
2009-08-22 11:41:10 +00:00
|
|
|
unsigned NumLocalSymbols = LocalSymbolData.size();
|
|
|
|
unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
|
|
|
|
unsigned NumExternalSymbols = ExternalSymbolData.size();
|
|
|
|
unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
|
|
|
|
unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
|
2009-08-24 11:56:58 +00:00
|
|
|
unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
|
|
|
|
unsigned NumSymTabSymbols =
|
|
|
|
NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
|
|
|
|
uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
|
|
|
|
uint64_t IndirectSymbolOffset = 0;
|
|
|
|
|
|
|
|
// If used, the indirect symbols are written after the section data.
|
|
|
|
if (NumIndirectSymbols)
|
2009-08-26 13:58:10 +00:00
|
|
|
IndirectSymbolOffset = RelocTableEnd;
|
2009-08-24 11:56:58 +00:00
|
|
|
|
|
|
|
// The symbol table is written after the indirect symbol data.
|
2009-08-26 13:58:10 +00:00
|
|
|
uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
|
2009-08-24 11:56:58 +00:00
|
|
|
|
|
|
|
// The string table is written after symbol table.
|
|
|
|
uint64_t StringTableOffset =
|
2010-03-13 22:49:35 +00:00
|
|
|
SymbolTableOffset + NumSymTabSymbols * (Is64Bit ? Nlist64Size :
|
|
|
|
Nlist32Size);
|
2009-08-24 11:56:58 +00:00
|
|
|
WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
|
|
|
|
StringTableOffset, StringTable.size());
|
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
|
|
|
|
FirstExternalSymbol, NumExternalSymbols,
|
|
|
|
FirstUndefinedSymbol, NumUndefinedSymbols,
|
|
|
|
IndirectSymbolOffset, NumIndirectSymbols);
|
|
|
|
}
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// Write the actual section data.
|
2010-03-19 07:09:33 +00:00
|
|
|
for (MCAssembler::const_iterator it = Asm.begin(),
|
|
|
|
ie = Asm.end(); it != ie; ++it)
|
2010-03-19 09:28:55 +00:00
|
|
|
WriteFileData(OS, *it, this);
|
2009-08-22 10:13:24 +00:00
|
|
|
|
2009-08-28 05:49:04 +00:00
|
|
|
// Write the extra padding.
|
|
|
|
WriteZeros(SectionDataPadding);
|
|
|
|
|
2009-08-26 13:58:10 +00:00
|
|
|
// Write the relocation entries.
|
2010-03-19 07:09:33 +00:00
|
|
|
for (MCAssembler::const_iterator it = Asm.begin(),
|
2010-03-19 07:09:18 +00:00
|
|
|
ie = Asm.end(); it != ie; ++it) {
|
|
|
|
// Write the section relocation entries, in reverse order to match 'as'
|
|
|
|
// (approximately, the exact algorithm is more complicated than this).
|
|
|
|
std::vector<MachRelocationEntry> &Relocs = Relocations[it];
|
|
|
|
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
|
|
|
Write32(Relocs[e - i - 1].Word0);
|
|
|
|
Write32(Relocs[e - i - 1].Word1);
|
|
|
|
}
|
2009-08-26 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2009-08-22 10:13:24 +00:00
|
|
|
// Write the symbol table data, if used.
|
|
|
|
if (NumSymbols) {
|
2009-08-24 11:56:58 +00:00
|
|
|
// Write the indirect symbol entries.
|
2010-03-19 07:09:33 +00:00
|
|
|
for (MCAssembler::const_indirect_symbol_iterator
|
2009-08-26 00:18:21 +00:00
|
|
|
it = Asm.indirect_symbol_begin(),
|
|
|
|
ie = Asm.indirect_symbol_end(); it != ie; ++it) {
|
|
|
|
// Indirect symbols in the non lazy symbol pointer section have some
|
|
|
|
// special handling.
|
|
|
|
const MCSectionMachO &Section =
|
|
|
|
static_cast<const MCSectionMachO&>(it->SectionData->getSection());
|
2010-03-15 21:56:38 +00:00
|
|
|
if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
|
2009-08-26 00:18:21 +00:00
|
|
|
// If this symbol is defined and internal, mark it as such.
|
|
|
|
if (it->Symbol->isDefined() &&
|
2010-03-10 20:58:31 +00:00
|
|
|
!Asm.getSymbolData(*it->Symbol).isExternal()) {
|
2009-08-26 00:18:21 +00:00
|
|
|
uint32_t Flags = ISF_Local;
|
|
|
|
if (it->Symbol->isAbsolute())
|
|
|
|
Flags |= ISF_Absolute;
|
|
|
|
Write32(Flags);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-10 20:58:31 +00:00
|
|
|
Write32(Asm.getSymbolData(*it->Symbol).getIndex());
|
2009-08-26 00:18:21 +00:00
|
|
|
}
|
2009-08-22 10:13:24 +00:00
|
|
|
|
2009-08-24 11:56:58 +00:00
|
|
|
// FIXME: Check that offsets match computed ones.
|
2009-08-22 10:13:24 +00:00
|
|
|
|
|
|
|
// Write the symbol table entries.
|
2009-08-22 11:41:10 +00:00
|
|
|
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
|
2010-03-13 22:49:35 +00:00
|
|
|
WriteNlist(LocalSymbolData[i]);
|
2009-08-22 11:41:10 +00:00
|
|
|
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
|
2010-03-13 22:49:35 +00:00
|
|
|
WriteNlist(ExternalSymbolData[i]);
|
2009-08-22 11:41:10 +00:00
|
|
|
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
|
2010-03-13 22:49:35 +00:00
|
|
|
WriteNlist(UndefinedSymbolData[i]);
|
2009-08-22 10:13:24 +00:00
|
|
|
|
|
|
|
// Write the string table.
|
|
|
|
OS << StringTable.str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
/* *** */
|
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
|
|
|
|
}
|
|
|
|
|
2009-08-26 02:48:04 +00:00
|
|
|
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
|
2009-08-21 18:29:01 +00:00
|
|
|
: Kind(_Kind),
|
2009-08-26 02:48:04 +00:00
|
|
|
Parent(_Parent),
|
2009-08-21 18:29:01 +00:00
|
|
|
FileSize(~UINT64_C(0))
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
{
|
2009-08-26 02:48:04 +00:00
|
|
|
if (Parent)
|
|
|
|
Parent->getFragmentList().push_back(this);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
MCFragment::~MCFragment() {
|
|
|
|
}
|
|
|
|
|
2009-08-26 02:48:04 +00:00
|
|
|
uint64_t MCFragment::getAddress() const {
|
|
|
|
assert(getParent() && "Missing Section!");
|
|
|
|
return getParent()->getAddress() + Offset;
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
/* *** */
|
|
|
|
|
2009-08-27 00:38:04 +00:00
|
|
|
MCSectionData::MCSectionData() : Section(0) {}
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
2009-08-27 00:38:04 +00:00
|
|
|
: Section(&_Section),
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
Alignment(1),
|
2009-08-26 02:48:04 +00:00
|
|
|
Address(~UINT64_C(0)),
|
2009-08-26 04:13:32 +00:00
|
|
|
Size(~UINT64_C(0)),
|
2009-08-26 13:58:10 +00:00
|
|
|
FileSize(~UINT64_C(0)),
|
2010-02-02 21:44:01 +00:00
|
|
|
HasInstructions(false)
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
{
|
|
|
|
if (A)
|
|
|
|
A->getSectionList().push_back(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *** */
|
|
|
|
|
2009-09-01 04:09:03 +00:00
|
|
|
MCSymbolData::MCSymbolData() : Symbol(0) {}
|
2009-08-22 10:13:24 +00:00
|
|
|
|
2009-08-31 08:08:06 +00:00
|
|
|
MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment,
|
2009-08-22 10:13:24 +00:00
|
|
|
uint64_t _Offset, MCAssembler *A)
|
2009-09-01 04:09:03 +00:00
|
|
|
: Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset),
|
2009-08-28 07:08:35 +00:00
|
|
|
IsExternal(false), IsPrivateExtern(false),
|
|
|
|
CommonSize(0), CommonAlign(0), Flags(0), Index(0)
|
2009-08-22 10:13:24 +00:00
|
|
|
{
|
|
|
|
if (A)
|
|
|
|
A->getSymbolList().push_back(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *** */
|
|
|
|
|
2010-03-11 01:34:27 +00:00
|
|
|
MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
|
|
|
|
raw_ostream &_OS)
|
|
|
|
: Context(_Context), Backend(_Backend), OS(_OS), SubsectionsViaSymbols(false)
|
2009-08-26 21:22:22 +00:00
|
|
|
{
|
|
|
|
}
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
|
|
|
|
MCAssembler::~MCAssembler() {
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:18:12 +00:00
|
|
|
static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
|
|
|
|
const MCAsmFixup &Fixup,
|
|
|
|
const MCDataFragment *DF,
|
|
|
|
const MCValue Target,
|
|
|
|
const MCSection *BaseSection) {
|
|
|
|
// The effective fixup address is
|
|
|
|
// addr(atom(A)) + offset(A)
|
|
|
|
// - addr(atom(B)) - offset(B)
|
|
|
|
// - addr(<base symbol>) + <fixup offset from base symbol>
|
|
|
|
// and the offsets are not relocatable, so the fixup is fully resolved when
|
|
|
|
// addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0.
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// 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 consider symbol differences fully resolved.
|
|
|
|
|
|
|
|
// Non-relative fixups are only resolved if constant.
|
|
|
|
if (!BaseSection)
|
|
|
|
return Target.isAbsolute();
|
|
|
|
|
|
|
|
// Otherwise, relative fixups are only resolved if not a difference and the
|
|
|
|
// target is a temporary in the same section.
|
|
|
|
if (Target.isAbsolute() || Target.getSymB())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
|
|
|
if (!A->isTemporary() || !A->isInSection() ||
|
|
|
|
&A->getSection() != BaseSection)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:18:18 +00:00
|
|
|
static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
|
|
|
|
const MCAsmFixup &Fixup,
|
|
|
|
const MCDataFragment *DF,
|
|
|
|
const MCValue Target,
|
|
|
|
const MCSymbolData *BaseSymbol) {
|
|
|
|
// The effective fixup address is
|
|
|
|
// addr(atom(A)) + offset(A)
|
|
|
|
// - addr(atom(B)) - offset(B)
|
|
|
|
// - addr(BaseSymbol) + <fixup offset from base symbol>
|
|
|
|
// and the offsets are not relocatable, so the fixup is fully resolved when
|
|
|
|
// addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
|
|
|
|
//
|
|
|
|
// Note that "false" is almost always conservatively correct (it means we emit
|
|
|
|
// a relocation which is unnecessary), except when it would force us to emit a
|
|
|
|
// relocation which the target cannot encode.
|
|
|
|
|
|
|
|
const MCSymbolData *A_Base = 0, *B_Base = 0;
|
|
|
|
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
|
|
|
// Modified symbol references cannot be resolved.
|
|
|
|
if (A->getKind() != MCSymbolRefExpr::VK_None)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
|
|
|
|
if (!A_Base)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
|
|
|
// Modified symbol references cannot be resolved.
|
|
|
|
if (B->getKind() != MCSymbolRefExpr::VK_None)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
|
|
|
|
if (!B_Base)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no base, A and B have to be the same atom for this fixup to be
|
|
|
|
// fully resolved.
|
|
|
|
if (!BaseSymbol)
|
|
|
|
return A_Base == B_Base;
|
|
|
|
|
|
|
|
// Otherwise, B must be missing and A must be the base.
|
|
|
|
return !B_Base && BaseSymbol == A_Base;
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:18:09 +00:00
|
|
|
bool MCAssembler::isSymbolLinkerVisible(const MCSymbolData *SD) const {
|
|
|
|
// Non-temporary labels should always be visible to the linker.
|
|
|
|
if (!SD->getSymbol().isTemporary())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Absolute temporary labels are never visible.
|
|
|
|
if (!SD->getFragment())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Otherwise, check if the section requires symbols even for temporary labels.
|
|
|
|
return getBackend().doesSectionRequireSymbols(
|
|
|
|
SD->getFragment()->getParent()->getSection());
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:18:15 +00:00
|
|
|
const MCSymbolData *MCAssembler::getAtomForAddress(const MCSectionData *Section,
|
|
|
|
uint64_t Address) const {
|
|
|
|
const MCSymbolData *Best = 0;
|
|
|
|
for (MCAssembler::const_symbol_iterator it = symbol_begin(),
|
|
|
|
ie = symbol_end(); it != ie; ++it) {
|
|
|
|
// Ignore non-linker visible symbols.
|
|
|
|
if (!isSymbolLinkerVisible(it))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Ignore symbols not in the same section.
|
|
|
|
if (!it->getFragment() || it->getFragment()->getParent() != Section)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Otherwise, find the closest symbol preceding this address (ties are
|
|
|
|
// resolved in favor of the last defined symbol).
|
|
|
|
if (it->getAddress() <= Address &&
|
|
|
|
(!Best || it->getAddress() >= Best->getAddress()))
|
|
|
|
Best = it;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Best;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {
|
|
|
|
// Linker visible symbols define atoms.
|
|
|
|
if (isSymbolLinkerVisible(SD))
|
|
|
|
return SD;
|
|
|
|
|
|
|
|
// Absolute and undefined symbols have no defining atom.
|
|
|
|
if (!SD->getFragment())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Otherwise, search by address.
|
|
|
|
return getAtomForAddress(SD->getFragment()->getParent(), SD->getAddress());
|
|
|
|
}
|
|
|
|
|
2010-03-12 21:00:49 +00:00
|
|
|
bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, MCAsmFixup &Fixup,
|
|
|
|
MCDataFragment *DF,
|
|
|
|
MCValue &Target, uint64_t &Value) const {
|
|
|
|
if (!Fixup.Value->EvaluateAsRelocatable(Target, &Layout))
|
|
|
|
llvm_report_error("expected relocatable expression");
|
|
|
|
|
|
|
|
// FIXME: How do non-scattered symbols work in ELF? I presume the linker
|
|
|
|
// doesn't support small relocations, but then under what criteria does the
|
|
|
|
// assembler allow symbol differences?
|
|
|
|
|
|
|
|
Value = Target.getConstant();
|
|
|
|
|
|
|
|
bool IsResolved = true, IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
2010-03-18 00:59:10 +00:00
|
|
|
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
|
|
|
if (A->getSymbol().isDefined())
|
|
|
|
Value += getSymbolData(A->getSymbol()).getAddress();
|
2010-03-12 21:00:49 +00:00
|
|
|
else
|
|
|
|
IsResolved = false;
|
|
|
|
}
|
2010-03-18 00:59:10 +00:00
|
|
|
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
|
|
|
if (B->getSymbol().isDefined())
|
|
|
|
Value -= getSymbolData(B->getSymbol()).getAddress();
|
2010-03-12 21:00:49 +00:00
|
|
|
else
|
|
|
|
IsResolved = false;
|
2010-03-19 03:18:12 +00:00
|
|
|
}
|
2010-03-12 21:00:49 +00:00
|
|
|
|
2010-03-19 03:18:12 +00:00
|
|
|
// If we are using scattered symbols, determine whether this value is actually
|
|
|
|
// resolved; scattering may cause atoms to move.
|
|
|
|
if (IsResolved && getBackend().hasScatteredSymbols()) {
|
|
|
|
if (getBackend().hasReliableSymbolDifference()) {
|
2010-03-19 03:18:18 +00:00
|
|
|
// If this is a PCrel relocation, find the base atom (identified by its
|
|
|
|
// symbol) that the fixup value is relative to.
|
|
|
|
const MCSymbolData *BaseSymbol = 0;
|
|
|
|
if (IsPCRel) {
|
|
|
|
BaseSymbol = getAtomForAddress(
|
|
|
|
DF->getParent(), DF->getAddress() + Fixup.Offset);
|
|
|
|
if (!BaseSymbol)
|
|
|
|
IsResolved = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsResolved)
|
|
|
|
IsResolved = isScatteredFixupFullyResolved(*this, Fixup, DF, Target,
|
|
|
|
BaseSymbol);
|
2010-03-19 03:18:12 +00:00
|
|
|
} else {
|
|
|
|
const MCSection *BaseSection = 0;
|
|
|
|
if (IsPCRel)
|
|
|
|
BaseSection = &DF->getParent()->getSection();
|
|
|
|
|
|
|
|
IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, DF, Target,
|
|
|
|
BaseSection);
|
|
|
|
}
|
2010-03-12 21:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IsPCRel)
|
2010-03-13 02:38:00 +00:00
|
|
|
Value -= DF->getAddress() + Fixup.Offset;
|
2010-03-12 21:00:49 +00:00
|
|
|
|
|
|
|
return IsResolved;
|
|
|
|
}
|
|
|
|
|
2009-08-28 05:49:04 +00:00
|
|
|
void MCAssembler::LayoutSection(MCSectionData &SD) {
|
2010-03-11 05:53:33 +00:00
|
|
|
MCAsmLayout Layout(*this);
|
2009-08-26 04:13:32 +00:00
|
|
|
uint64_t Address = SD.getAddress();
|
2009-08-21 18:29:01 +00:00
|
|
|
|
|
|
|
for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
|
|
|
|
MCFragment &F = *it;
|
2009-08-21 23:07:38 +00:00
|
|
|
|
2009-08-26 04:13:32 +00:00
|
|
|
F.setOffset(Address - SD.getAddress());
|
2009-08-21 23:07:38 +00:00
|
|
|
|
|
|
|
// Evaluate fragment size.
|
|
|
|
switch (F.getKind()) {
|
|
|
|
case MCFragment::FT_Align: {
|
|
|
|
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
uint64_t Size = OffsetToAlignment(Address, AF.getAlignment());
|
2009-08-26 04:13:32 +00:00
|
|
|
if (Size > AF.getMaxBytesToEmit())
|
2009-08-21 23:07:38 +00:00
|
|
|
AF.setFileSize(0);
|
|
|
|
else
|
2009-08-26 04:13:32 +00:00
|
|
|
AF.setFileSize(Size);
|
2009-08-21 23:07:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MCFragment::FT_Data:
|
2010-02-13 09:28:32 +00:00
|
|
|
case MCFragment::FT_Fill:
|
2009-08-21 23:07:38 +00:00
|
|
|
F.setFileSize(F.getMaxFileSize());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MCFragment::FT_Org: {
|
|
|
|
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
|
|
|
|
2010-03-11 05:53:33 +00:00
|
|
|
int64_t TargetLocation;
|
|
|
|
if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, &Layout))
|
|
|
|
llvm_report_error("expected assembly-time absolute expression");
|
2009-08-21 23:07:38 +00:00
|
|
|
|
|
|
|
// FIXME: We need a way to communicate this error.
|
2010-03-11 05:53:33 +00:00
|
|
|
int64_t Offset = TargetLocation - F.getOffset();
|
|
|
|
if (Offset < 0)
|
|
|
|
llvm_report_error("invalid .org offset '" + Twine(TargetLocation) +
|
|
|
|
"' (at offset '" + Twine(F.getOffset()) + "'");
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2010-03-11 05:53:33 +00:00
|
|
|
F.setFileSize(Offset);
|
2009-08-21 23:07:38 +00:00
|
|
|
break;
|
2009-10-16 01:58:15 +00:00
|
|
|
}
|
2009-08-28 05:49:21 +00:00
|
|
|
|
|
|
|
case MCFragment::FT_ZeroFill: {
|
|
|
|
MCZeroFillFragment &ZFF = cast<MCZeroFillFragment>(F);
|
|
|
|
|
|
|
|
// Align the fragment offset; it is safe to adjust the offset freely since
|
|
|
|
// this is only in virtual sections.
|
2010-03-08 21:10:42 +00:00
|
|
|
Address = RoundUpToAlignment(Address, ZFF.getAlignment());
|
|
|
|
F.setOffset(Address - SD.getAddress());
|
2009-08-28 05:49:21 +00:00
|
|
|
|
|
|
|
// FIXME: This is misnamed.
|
|
|
|
F.setFileSize(ZFF.getSize());
|
|
|
|
break;
|
|
|
|
}
|
2009-08-21 23:07:38 +00:00
|
|
|
}
|
|
|
|
|
2009-08-26 04:13:32 +00:00
|
|
|
Address += F.getFileSize();
|
2009-08-21 18:29:01 +00:00
|
|
|
}
|
|
|
|
|
2009-08-26 04:13:32 +00:00
|
|
|
// Set the section sizes.
|
|
|
|
SD.setSize(Address - SD.getAddress());
|
2009-08-28 05:49:21 +00:00
|
|
|
if (isVirtualSection(SD.getSection()))
|
|
|
|
SD.setFileSize(0);
|
|
|
|
else
|
|
|
|
SD.setFileSize(Address - SD.getAddress());
|
2009-08-21 18:29:01 +00:00
|
|
|
}
|
|
|
|
|
2010-02-23 18:26:34 +00:00
|
|
|
/// WriteNopData - Write optimal nops to the output file for the \arg Count
|
|
|
|
/// bytes. This returns the number of bytes written. It may return 0 if
|
|
|
|
/// the \arg Count is more than the maximum optimal nops.
|
|
|
|
///
|
|
|
|
/// FIXME this is X86 32-bit specific and should move to a better place.
|
2010-03-19 09:28:55 +00:00
|
|
|
static uint64_t WriteNopData(uint64_t Count, MCObjectWriter *OW) {
|
2010-02-23 21:41:24 +00:00
|
|
|
static const uint8_t Nops[16][16] = {
|
|
|
|
// nop
|
|
|
|
{0x90},
|
|
|
|
// xchg %ax,%ax
|
|
|
|
{0x66, 0x90},
|
|
|
|
// nopl (%[re]ax)
|
|
|
|
{0x0f, 0x1f, 0x00},
|
|
|
|
// nopl 0(%[re]ax)
|
|
|
|
{0x0f, 0x1f, 0x40, 0x00},
|
|
|
|
// nopl 0(%[re]ax,%[re]ax,1)
|
|
|
|
{0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
|
|
// nopw 0(%[re]ax,%[re]ax,1)
|
|
|
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
|
|
// nopl 0L(%[re]ax)
|
|
|
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopl 0L(%[re]ax,%[re]ax,1)
|
|
|
|
{0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopw 0L(%[re]ax,%[re]ax,1)
|
|
|
|
{0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopw %cs:0L(%[re]ax,%[re]ax,1)
|
|
|
|
{0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopl 0(%[re]ax,%[re]ax,1)
|
|
|
|
// nopw 0(%[re]ax,%[re]ax,1)
|
|
|
|
{0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
|
|
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
|
|
// nopw 0(%[re]ax,%[re]ax,1)
|
|
|
|
// nopw 0(%[re]ax,%[re]ax,1)
|
|
|
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
|
|
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
|
|
// nopw 0(%[re]ax,%[re]ax,1)
|
|
|
|
// nopl 0L(%[re]ax) */
|
|
|
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
|
|
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopl 0L(%[re]ax)
|
|
|
|
// nopl 0L(%[re]ax)
|
|
|
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
|
|
// nopl 0L(%[re]ax)
|
|
|
|
// nopl 0L(%[re]ax,%[re]ax,1)
|
|
|
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Count > 15)
|
|
|
|
return 0;
|
|
|
|
|
2010-02-23 18:26:34 +00:00
|
|
|
for (uint64_t i = 0; i < Count; i++)
|
2010-03-19 09:28:55 +00:00
|
|
|
OW->Write8(uint8_t(Nops[Count - 1][i]));
|
2010-02-23 18:26:34 +00:00
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
/// WriteFileData - Write the \arg F data to the output file.
|
|
|
|
static void WriteFileData(raw_ostream &OS, const MCFragment &F,
|
2010-03-19 09:28:55 +00:00
|
|
|
MCObjectWriter *OW) {
|
2009-08-21 18:29:01 +00:00
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-25 21:10:45 +00:00
|
|
|
++EmittedFragments;
|
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
// FIXME: Embed in fragments instead?
|
|
|
|
switch (F.getKind()) {
|
2009-08-21 23:07:38 +00:00
|
|
|
case MCFragment::FT_Align: {
|
|
|
|
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
|
|
|
uint64_t Count = AF.getFileSize() / AF.getValueSize();
|
|
|
|
|
|
|
|
// FIXME: This error shouldn't actually occur (the front end should emit
|
|
|
|
// multiple .align directives to enforce the semantics it wants), but is
|
|
|
|
// severe enough that we want to report it. How to handle this?
|
|
|
|
if (Count * AF.getValueSize() != AF.getFileSize())
|
2009-10-16 01:58:15 +00:00
|
|
|
llvm_report_error("undefined .align directive, value size '" +
|
|
|
|
Twine(AF.getValueSize()) +
|
2009-08-21 23:07:38 +00:00
|
|
|
"' is not a divisor of padding size '" +
|
|
|
|
Twine(AF.getFileSize()) + "'");
|
|
|
|
|
2010-02-23 18:26:34 +00:00
|
|
|
// See if we are aligning with nops, and if so do that first to try to fill
|
|
|
|
// the Count bytes. Then if that did not fill any bytes or there are any
|
|
|
|
// bytes left to fill use the the Value and ValueSize to fill the rest.
|
|
|
|
if (AF.getEmitNops()) {
|
2010-03-19 09:28:55 +00:00
|
|
|
uint64_t NopByteCount = WriteNopData(Count, OW);
|
2010-02-23 18:26:34 +00:00
|
|
|
Count -= NopByteCount;
|
|
|
|
}
|
|
|
|
|
2009-08-21 23:07:38 +00:00
|
|
|
for (uint64_t i = 0; i != Count; ++i) {
|
|
|
|
switch (AF.getValueSize()) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid size!");
|
2010-03-19 09:28:55 +00:00
|
|
|
case 1: OW->Write8 (uint8_t (AF.getValue())); break;
|
|
|
|
case 2: OW->Write16(uint16_t(AF.getValue())); break;
|
|
|
|
case 4: OW->Write32(uint32_t(AF.getValue())); break;
|
|
|
|
case 8: OW->Write64(uint64_t(AF.getValue())); break;
|
2009-08-21 23:07:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-08-21 18:29:01 +00:00
|
|
|
|
2010-02-13 09:28:15 +00:00
|
|
|
case MCFragment::FT_Data: {
|
2009-08-21 18:29:01 +00:00
|
|
|
OS << cast<MCDataFragment>(F).getContents().str();
|
|
|
|
break;
|
2010-02-13 09:28:15 +00:00
|
|
|
}
|
2009-08-21 18:29:01 +00:00
|
|
|
|
|
|
|
case MCFragment::FT_Fill: {
|
|
|
|
MCFillFragment &FF = cast<MCFillFragment>(F);
|
|
|
|
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
|
|
|
|
switch (FF.getValueSize()) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid size!");
|
2010-03-19 09:28:55 +00:00
|
|
|
case 1: OW->Write8 (uint8_t (FF.getValue())); break;
|
|
|
|
case 2: OW->Write16(uint16_t(FF.getValue())); break;
|
|
|
|
case 4: OW->Write32(uint32_t(FF.getValue())); break;
|
|
|
|
case 8: OW->Write64(uint64_t(FF.getValue())); break;
|
2009-08-21 18:29:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-21 23:07:38 +00:00
|
|
|
case MCFragment::FT_Org: {
|
|
|
|
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
|
|
|
|
|
|
|
for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i)
|
2010-03-19 09:28:55 +00:00
|
|
|
OW->Write8(uint8_t(OF.getValue()));
|
2009-08-21 23:07:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2009-08-28 05:49:21 +00:00
|
|
|
|
|
|
|
case MCFragment::FT_ZeroFill: {
|
|
|
|
assert(0 && "Invalid zero fill fragment in concrete section!");
|
|
|
|
break;
|
|
|
|
}
|
2009-08-21 18:29:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2010-03-19 09:28:55 +00:00
|
|
|
MCObjectWriter *OW) {
|
2009-08-28 05:49:21 +00:00
|
|
|
// Ignore virtual sections.
|
|
|
|
if (isVirtualSection(SD.getSection())) {
|
|
|
|
assert(SD.getFileSize() == 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
2009-10-16 01:58:15 +00:00
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
for (MCSectionData::const_iterator it = SD.begin(),
|
|
|
|
ie = SD.end(); it != ie; ++it)
|
2010-03-19 09:28:55 +00:00
|
|
|
WriteFileData(OS, *it, OW);
|
2009-08-21 18:29:01 +00:00
|
|
|
|
2009-08-26 04:13:32 +00:00
|
|
|
// Add section padding.
|
|
|
|
assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!");
|
2010-03-19 09:28:55 +00:00
|
|
|
OW->WriteZeros(SD.getFileSize() - SD.getSize());
|
2009-08-26 04:13:32 +00:00
|
|
|
|
2009-08-21 18:29:01 +00:00
|
|
|
assert(OS.tell() - Start == SD.getFileSize());
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00
|
|
|
void MCAssembler::Finish() {
|
2010-02-13 09:28:03 +00:00
|
|
|
DEBUG_WITH_TYPE("mc-dump", {
|
|
|
|
llvm::errs() << "assembler backend - pre-layout\n--\n";
|
|
|
|
dump(); });
|
|
|
|
|
2010-03-12 22:07:14 +00:00
|
|
|
// Layout until everything fits.
|
|
|
|
while (LayoutOnce())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DEBUG_WITH_TYPE("mc-dump", {
|
|
|
|
llvm::errs() << "assembler backend - post-layout\n--\n";
|
|
|
|
dump(); });
|
|
|
|
|
2010-03-13 22:10:17 +00:00
|
|
|
// FIXME: Factor out MCObjectWriter.
|
|
|
|
bool Is64Bit = StringRef(getBackend().getTarget().getName()) == "x86-64";
|
|
|
|
MachObjectWriter MOW(OS, Is64Bit);
|
2010-03-19 07:09:33 +00:00
|
|
|
|
|
|
|
// Allow the object writer a chance to perform post-layout binding (for
|
|
|
|
// example, to set the index fields in the symbol data).
|
|
|
|
MOW.ExecutePostLayoutBinding(*this);
|
|
|
|
|
2010-03-19 07:09:47 +00:00
|
|
|
// Evaluate and apply the fixups, generating relocation entries as necessary.
|
2010-03-19 09:28:55 +00:00
|
|
|
//
|
|
|
|
// FIXME: Share layout object.
|
2010-03-19 07:09:47 +00:00
|
|
|
MCAsmLayout Layout(*this);
|
|
|
|
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
for (MCSectionData::iterator it2 = it->begin(),
|
|
|
|
ie2 = it->end(); it2 != ie2; ++it2) {
|
|
|
|
MCDataFragment *DF = dyn_cast<MCDataFragment>(it2);
|
|
|
|
if (!DF)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(),
|
|
|
|
ie3 = DF->fixup_end(); it3 != ie3; ++it3) {
|
|
|
|
MCAsmFixup &Fixup = *it3;
|
|
|
|
|
|
|
|
// Evaluate the fixup.
|
|
|
|
MCValue Target;
|
|
|
|
uint64_t FixedValue;
|
|
|
|
if (!EvaluateFixup(Layout, Fixup, DF, Target, FixedValue)) {
|
|
|
|
// The fixup was unresolved, we need a relocation. Inform the object
|
|
|
|
// writer of the relocation, and give it an opportunity to adjust the
|
|
|
|
// fixup value if need be.
|
|
|
|
MOW.RecordRelocation(*this, *DF, Fixup, Target, FixedValue);
|
|
|
|
}
|
|
|
|
|
2010-03-19 09:28:12 +00:00
|
|
|
getBackend().ApplyFixup(Fixup, *DF, FixedValue);
|
2010-03-19 07:09:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-19 07:09:33 +00:00
|
|
|
// Write the object file.
|
2010-03-12 22:07:14 +00:00
|
|
|
MOW.WriteObject(*this);
|
|
|
|
|
|
|
|
OS.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MCAssembler::FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF) {
|
|
|
|
// FIXME: Share layout object.
|
|
|
|
MCAsmLayout Layout(*this);
|
|
|
|
|
|
|
|
// Currently we only need to relax X86::reloc_pcrel_1byte.
|
|
|
|
if (unsigned(Fixup.Kind) != X86::reloc_pcrel_1byte)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If we cannot resolve the fixup value, it requires relaxation.
|
|
|
|
MCValue Target;
|
|
|
|
uint64_t Value;
|
|
|
|
if (!EvaluateFixup(Layout, Fixup, DF, Target, Value))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Otherwise, relax if the value is too big for a (signed) i8.
|
|
|
|
return int64_t(Value) != int64_t(int8_t(Value));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MCAssembler::LayoutOnce() {
|
2009-08-28 05:49:21 +00:00
|
|
|
// Layout the concrete sections and fragments.
|
2009-08-26 02:48:04 +00:00
|
|
|
uint64_t Address = 0;
|
2009-08-28 05:49:04 +00:00
|
|
|
MCSectionData *Prev = 0;
|
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
2009-08-26 04:13:32 +00:00
|
|
|
MCSectionData &SD = *it;
|
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
// Skip virtual sections.
|
|
|
|
if (isVirtualSection(SD.getSection()))
|
|
|
|
continue;
|
|
|
|
|
2009-08-28 05:49:04 +00:00
|
|
|
// Align this section if necessary by adding padding bytes to the previous
|
|
|
|
// section.
|
|
|
|
if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) {
|
|
|
|
assert(Prev && "Missing prev section!");
|
|
|
|
Prev->setFileSize(Prev->getFileSize() + Pad);
|
|
|
|
Address += Pad;
|
|
|
|
}
|
2009-08-26 04:13:32 +00:00
|
|
|
|
|
|
|
// Layout the section fragments and its size.
|
|
|
|
SD.setAddress(Address);
|
2009-08-28 05:49:04 +00:00
|
|
|
LayoutSection(SD);
|
2009-08-26 04:13:32 +00:00
|
|
|
Address += SD.getFileSize();
|
2009-08-28 05:49:04 +00:00
|
|
|
|
|
|
|
Prev = &SD;
|
2009-08-26 02:48:04 +00:00
|
|
|
}
|
2009-08-21 18:29:01 +00:00
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
// Layout the virtual sections.
|
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
MCSectionData &SD = *it;
|
|
|
|
|
|
|
|
if (!isVirtualSection(SD.getSection()))
|
|
|
|
continue;
|
|
|
|
|
2010-03-08 22:03:42 +00:00
|
|
|
// Align this section if necessary by adding padding bytes to the previous
|
|
|
|
// section.
|
2010-03-09 01:12:20 +00:00
|
|
|
if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment()))
|
2010-03-08 22:03:42 +00:00
|
|
|
Address += Pad;
|
|
|
|
|
2009-08-28 05:49:21 +00:00
|
|
|
SD.setAddress(Address);
|
|
|
|
LayoutSection(SD);
|
|
|
|
Address += SD.getSize();
|
|
|
|
}
|
|
|
|
|
2010-03-12 22:07:14 +00:00
|
|
|
// Scan the fixups in order and relax any that don't fit.
|
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
MCSectionData &SD = *it;
|
2010-02-13 09:28:03 +00:00
|
|
|
|
2010-03-12 22:07:14 +00:00
|
|
|
for (MCSectionData::iterator it2 = SD.begin(),
|
|
|
|
ie2 = SD.end(); it2 != ie2; ++it2) {
|
|
|
|
MCDataFragment *DF = dyn_cast<MCDataFragment>(it2);
|
|
|
|
if (!DF)
|
|
|
|
continue;
|
2009-08-21 18:29:01 +00:00
|
|
|
|
2010-03-12 22:07:14 +00:00
|
|
|
for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(),
|
|
|
|
ie3 = DF->fixup_end(); it3 != ie3; ++it3) {
|
|
|
|
MCAsmFixup &Fixup = *it3;
|
|
|
|
|
|
|
|
// Check whether we need to relax this fixup.
|
|
|
|
if (!FixupNeedsRelaxation(Fixup, DF))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Relax the instruction.
|
|
|
|
//
|
|
|
|
// FIXME: This is a huge temporary hack which just looks for x86
|
|
|
|
// branches; the only thing we need to relax on x86 is
|
|
|
|
// 'X86::reloc_pcrel_1byte'. Once we have MCInst fragments, this will be
|
|
|
|
// replaced by a TargetAsmBackend hook (most likely tblgen'd) to relax
|
|
|
|
// an individual MCInst.
|
|
|
|
SmallVectorImpl<char> &C = DF->getContents();
|
|
|
|
uint64_t PrevOffset = Fixup.Offset;
|
|
|
|
unsigned Amt = 0;
|
|
|
|
|
|
|
|
// jcc instructions
|
|
|
|
if (unsigned(C[Fixup.Offset-1]) >= 0x70 &&
|
|
|
|
unsigned(C[Fixup.Offset-1]) <= 0x7f) {
|
|
|
|
C[Fixup.Offset] = C[Fixup.Offset-1] + 0x10;
|
|
|
|
C[Fixup.Offset-1] = char(0x0f);
|
|
|
|
++Fixup.Offset;
|
|
|
|
Amt = 4;
|
|
|
|
|
|
|
|
// jmp rel8
|
|
|
|
} else if (C[Fixup.Offset-1] == char(0xeb)) {
|
|
|
|
C[Fixup.Offset-1] = char(0xe9);
|
|
|
|
Amt = 3;
|
|
|
|
|
|
|
|
} else
|
|
|
|
llvm_unreachable("unknown 1 byte pcrel instruction!");
|
|
|
|
|
|
|
|
Fixup.Value = MCBinaryExpr::Create(
|
|
|
|
MCBinaryExpr::Sub, Fixup.Value,
|
|
|
|
MCConstantExpr::Create(3, getContext()),
|
|
|
|
getContext());
|
|
|
|
C.insert(C.begin() + Fixup.Offset, Amt, char(0));
|
|
|
|
Fixup.Kind = MCFixupKind(X86::reloc_pcrel_4byte);
|
|
|
|
|
|
|
|
// Update the remaining fixups, which have slid.
|
|
|
|
//
|
|
|
|
// FIXME: This is bad for performance, but will be eliminated by the
|
|
|
|
// move to MCInst specific fragments.
|
|
|
|
++it3;
|
|
|
|
for (; it3 != ie3; ++it3)
|
|
|
|
it3->Offset += Amt;
|
2010-02-13 09:28:03 +00:00
|
|
|
|
2010-03-12 22:07:14 +00:00
|
|
|
// Update all the symbols for this fragment, which may have slid.
|
|
|
|
//
|
|
|
|
// FIXME: This is really really bad for performance, but will be
|
|
|
|
// eliminated by the move to MCInst specific fragments.
|
|
|
|
for (MCAssembler::symbol_iterator it = symbol_begin(),
|
|
|
|
ie = symbol_end(); it != ie; ++it) {
|
|
|
|
MCSymbolData &SD = *it;
|
|
|
|
|
|
|
|
if (it->getFragment() != DF)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (SD.getOffset() > PrevOffset)
|
|
|
|
SD.setOffset(SD.getOffset() + Amt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restart layout.
|
|
|
|
//
|
|
|
|
// FIXME: This is O(N^2), but will be eliminated once we have a smart
|
|
|
|
// MCAsmLayout object.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2010-02-13 09:28:03 +00:00
|
|
|
|
|
|
|
// Debugging methods
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const MCAsmFixup &AF) {
|
2010-02-13 09:28:54 +00:00
|
|
|
OS << "<MCAsmFixup" << " Offset:" << AF.Offset << " Value:" << *AF.Value
|
|
|
|
<< " Kind:" << AF.Kind << ">";
|
2010-02-13 09:28:03 +00:00
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCFragment " << (void*) this << " Offset:" << Offset
|
|
|
|
<< " FileSize:" << FileSize;
|
|
|
|
|
|
|
|
OS << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAlignFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCAlignFragment ";
|
|
|
|
this->MCFragment::dump();
|
|
|
|
OS << "\n ";
|
|
|
|
OS << " Alignment:" << getAlignment()
|
|
|
|
<< " Value:" << getValue() << " ValueSize:" << getValueSize()
|
|
|
|
<< " MaxBytesToEmit:" << getMaxBytesToEmit() << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCDataFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCDataFragment ";
|
|
|
|
this->MCFragment::dump();
|
|
|
|
OS << "\n ";
|
|
|
|
OS << " Contents:[";
|
|
|
|
for (unsigned i = 0, e = getContents().size(); i != e; ++i) {
|
|
|
|
if (i) OS << ",";
|
|
|
|
OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
|
|
|
|
}
|
2010-02-13 09:28:54 +00:00
|
|
|
OS << "] (" << getContents().size() << " bytes)";
|
2010-02-13 09:28:43 +00:00
|
|
|
|
|
|
|
if (!getFixups().empty()) {
|
|
|
|
OS << ",\n ";
|
|
|
|
OS << " Fixups:[";
|
|
|
|
for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) {
|
2010-03-09 01:12:23 +00:00
|
|
|
if (it != fixup_begin()) OS << ",\n ";
|
2010-02-13 09:28:43 +00:00
|
|
|
OS << *it;
|
|
|
|
}
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << ">";
|
2010-02-13 09:28:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MCFillFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCFillFragment ";
|
|
|
|
this->MCFragment::dump();
|
|
|
|
OS << "\n ";
|
|
|
|
OS << " Value:" << getValue() << " ValueSize:" << getValueSize()
|
|
|
|
<< " Count:" << getCount() << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCOrgFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCOrgFragment ";
|
|
|
|
this->MCFragment::dump();
|
|
|
|
OS << "\n ";
|
|
|
|
OS << " Offset:" << getOffset() << " Value:" << getValue() << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCZeroFillFragment::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCZeroFillFragment ";
|
|
|
|
this->MCFragment::dump();
|
|
|
|
OS << "\n ";
|
|
|
|
OS << " Size:" << getSize() << " Alignment:" << getAlignment() << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCSectionData::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCSectionData";
|
|
|
|
OS << " Alignment:" << getAlignment() << " Address:" << Address
|
|
|
|
<< " Size:" << Size << " FileSize:" << FileSize
|
2010-03-09 01:12:23 +00:00
|
|
|
<< " Fragments:[\n ";
|
2010-02-13 09:28:03 +00:00
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
if (it != begin()) OS << ",\n ";
|
|
|
|
it->dump();
|
|
|
|
}
|
|
|
|
OS << "]>";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCSymbolData::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCSymbolData Symbol:" << getSymbol()
|
|
|
|
<< " Fragment:" << getFragment() << " Offset:" << getOffset()
|
|
|
|
<< " Flags:" << getFlags() << " Index:" << getIndex();
|
|
|
|
if (isCommon())
|
|
|
|
OS << " (common, size:" << getCommonSize()
|
|
|
|
<< " align: " << getCommonAlignment() << ")";
|
|
|
|
if (isExternal())
|
|
|
|
OS << " (external)";
|
|
|
|
if (isPrivateExtern())
|
|
|
|
OS << " (private extern)";
|
|
|
|
OS << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAssembler::dump() {
|
|
|
|
raw_ostream &OS = llvm::errs();
|
|
|
|
|
|
|
|
OS << "<MCAssembler\n";
|
2010-03-09 01:12:23 +00:00
|
|
|
OS << " Sections:[\n ";
|
2010-02-13 09:28:03 +00:00
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
if (it != begin()) OS << ",\n ";
|
|
|
|
it->dump();
|
|
|
|
}
|
|
|
|
OS << "],\n";
|
|
|
|
OS << " Symbols:[";
|
|
|
|
|
|
|
|
for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
|
2010-03-09 01:12:23 +00:00
|
|
|
if (it != symbol_begin()) OS << ",\n ";
|
2010-02-13 09:28:03 +00:00
|
|
|
it->dump();
|
|
|
|
}
|
|
|
|
OS << "]>\n";
|
|
|
|
}
|