Move implementation of WriterOptionsMachO to its own file. Reduced redundant

ivars in WriterOptionsMachO instead have its methods compute ivar interactions.
Refactor mach-o Reference Kinds and introduce abstract class KindHandler.
Split up StubAtoms.hpp by architecture.  Add support for 32-bit x86 stubs.

llvm-svn: 158336
This commit is contained in:
Nick Kledzik 2012-06-11 22:53:15 +00:00
parent 130adbc5a3
commit 40b68559e8
12 changed files with 1090 additions and 345 deletions

View File

@ -51,25 +51,27 @@ public:
enum Architecture {
arch_x86_64,
arch_x86,
arch_arm,
arch_armv6,
arch_armv7,
};
OutputKind outputKind() const { return _outputkind; }
Architecture architecture() const { return _architecture; }
StringRef archName() const { return _archName; }
uint64_t pageZeroSize() const { return _pageZeroSize; }
uint32_t cpuType() const { return _cpuType; }
uint32_t cpuSubtype() const { return _cpuSubtype; }
bool noTextRelocations() const { return _noTextRelocations; }
OutputKind outputKind() const { return _outputkind; }
Architecture architecture() const { return _architecture; }
StringRef archName() const;
uint32_t cpuType() const;
uint32_t cpuSubtype() const;
uint64_t pageZeroSize() const;
bool noTextRelocations() const { return _noTextRelocations; }
bool addEntryPointLoadCommand() const;
bool addUnixThreadLoadCommand() const;
StringRef entryPointName() const;
protected:
OutputKind _outputkind;
StringRef _archName;
Architecture _architecture;
uint64_t _pageZeroSize;
uint32_t _cpuType;
uint32_t _cpuSubtype;
bool _noTextRelocations;
StringRef _customEntryPointName;
};

View File

@ -1,4 +1,5 @@
add_lld_library(lldMachO
WriterMachO.cpp
WriterOptionsMachO.cpp
ReferenceKinds.cpp
)

View File

@ -131,7 +131,7 @@ private:
};
void mach_header::recordLoadCommand(const load_command *lc) {
inline void mach_header::recordLoadCommand(const load_command *lc) {
++ncmds;
sizeofcmds += lc->cmdsize;
}
@ -140,6 +140,7 @@ void mach_header::recordLoadCommand(const load_command *lc) {
enum {
LC_SEGMENT = 0x00000001,
LC_SYMTAB = 0x00000002,
LC_UNIXTHREAD = 0x00000005,
LC_LOAD_DYLIB = 0x0000000C,
LC_LOAD_DYLINKER = 0x0000000E,
LC_SEGMENT_64 = 0x00000019,
@ -375,6 +376,95 @@ public:
};
//
// The thread_command load command holds the set of initial register values
// for a dynamic executable. In reality, only the PC and SP are used.
//
class thread_command : public load_command {
public:
uint32_t fields_flavor;
uint32_t fields_count;
private:
uint32_t _cpuType;
uint8_t *_registerArray;
public:
thread_command(uint32_t cpuType, bool is64)
: load_command(LC_UNIXTHREAD, 16+registersBufferSize(cpuType), is64),
fields_count(registersBufferSize(cpuType)/4), _cpuType(cpuType) {
switch ( cpuType ) {
case CPU_TYPE_I386:
fields_flavor = 1; // i386_THREAD_STATE
break;
case CPU_TYPE_X86_64:
fields_flavor = 4; // x86_THREAD_STATE64;
break;
case CPU_TYPE_ARM:
fields_flavor = 1; // ARM_THREAD_STATE
break;
default:
assert(0 && "unsupported cpu type");
}
_registerArray = reinterpret_cast<uint8_t*>(
::calloc(registersBufferSize(cpuType), 1));
assert(_registerArray);
}
virtual void copyTo(uint8_t *to, bool swap=false) {
if ( swap ) {
assert(0 && "non-native endianness not supported yet");
}
else {
// in-memory matches on-disk, so copy fixed fields
::memcpy(to, (uint8_t*)&cmd, 16);
// that register array
::memcpy(&to[16], _registerArray, registersBufferSize(_cpuType));
}
}
void setPC(uint64_t pc) {
uint32_t *regs32 = reinterpret_cast<uint32_t*>(_registerArray);
uint64_t *regs64 = reinterpret_cast<uint64_t*>(_registerArray);
switch ( _cpuType ) {
case CPU_TYPE_I386:
regs32[10] = pc;
break;
case CPU_TYPE_X86_64:
regs64[16] = pc;
break;
case CPU_TYPE_ARM:
regs32[15] = pc;
break;
default:
assert(0 && "unsupported cpu type");
}
}
virtual ~thread_command() {
::free(_registerArray);
}
private:
uint32_t registersBufferSize(uint32_t cpuType) {
switch ( cpuType ) {
case CPU_TYPE_I386:
return 64; // i386_THREAD_STATE_COUNT * 4
case CPU_TYPE_X86_64:
return 168; // x86_THREAD_STATE64_COUNT * 4
case CPU_TYPE_ARM:
return 68; // ARM_THREAD_STATE_COUNT * 4
}
assert(0 && "unsupported cpu type");
return 0;
}
};
//
// The dylib_command load command holds the name/path of a dynamic shared

View File

@ -16,85 +16,299 @@
namespace lld {
namespace mach_o {
struct Mapping {
const char* string;
Reference::Kind value;
uint32_t flags;
};
//===----------------------------------------------------------------------===//
// KindHandler
//===----------------------------------------------------------------------===//
enum {
flagsNone = 0x0000,
flagsIsCallSite = 0x0001,
flagsUsesGOT = 0x0002,
flagsisGOTLoad = 0x0006,
flags32RipRel = 0x1000,
};
KindHandler::KindHandler() {
}
KindHandler::~KindHandler() {
}
static const Mapping sKindMappingsx86_64[] = {
{ "none", ReferenceKind::x86_64_none, flagsNone },
{ "call32", ReferenceKind::x86_64_call32, flagsIsCallSite | flags32RipRel },
{ "pcrel32", ReferenceKind::x86_64_pcRel32, flags32RipRel },
{ "gotLoad32", ReferenceKind::x86_64_gotLoad32, flagsisGOTLoad | flags32RipRel },
{ "gotUse32", ReferenceKind::x86_64_gotUse32, flagsUsesGOT | flags32RipRel },
{ "lea32wasGot", ReferenceKind::x86_64_lea32WasGot, flags32RipRel },
{ "lazyTarget", ReferenceKind::x86_64_lazyTarget, flagsNone },
{ "lazyImm", ReferenceKind::x86_64_lazyImm, flagsNone },
{ "gotTarget", ReferenceKind::x86_64_gotTarget, flagsNone },
{ "pointer64", ReferenceKind::x86_64_pointer64, flagsNone },
{ NULL, ReferenceKind::x86_64_none, flagsNone }
};
Reference::Kind ReferenceKind::fromString(StringRef kindName) {
for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
if ( kindName.equals(p->string) )
return p->value;
KindHandler *KindHandler::makeHandler(WriterOptionsMachO::Architecture arch) {
switch( arch ) {
case WriterOptionsMachO::arch_x86_64:
return new KindHandler_x86_64();
break;
case WriterOptionsMachO::arch_x86:
return new KindHandler_x86();
break;
case WriterOptionsMachO::arch_armv6:
case WriterOptionsMachO::arch_armv7:
return new KindHandler_arm();
break;
default:
assert(0 && "arch not supported");
}
assert(0 && "unknown darwin reference kind");
}
//===----------------------------------------------------------------------===//
// KindHandler_x86_64
//===----------------------------------------------------------------------===//
KindHandler_x86_64::~KindHandler_x86_64() {
}
Reference::Kind KindHandler_x86_64::stringToKind(StringRef str) {
if ( str.equals("none") )
return KindHandler_x86_64::none;
else if ( str.equals("call32") )
return KindHandler_x86_64::call32;
else if ( str.equals("ripRel32") )
return KindHandler_x86_64::ripRel32;
else if ( str.equals("gotLoad32") )
return KindHandler_x86_64::gotLoad32;
else if ( str.equals("gotUse32") )
return KindHandler_x86_64::gotUse32;
else if ( str.equals("pointer64") )
return KindHandler_x86_64::pointer64;
else if ( str.equals("lea32WasGot") )
return KindHandler_x86_64::lea32WasGot;
else if ( str.equals("lazyTarget") )
return KindHandler_x86_64::lazyTarget;
else if ( str.equals("lazyImm") )
return KindHandler_x86_64::lazyImm;
else if ( str.equals("gotTarget") )
return KindHandler_x86_64::gotTarget;
assert(0 && "invalid x86_64 Reference kind");
return 0;
}
StringRef ReferenceKind::toString(Reference::Kind kindValue) {
for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
if ( kindValue == p->value)
return p->string;
StringRef KindHandler_x86_64::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) {
case none:
return StringRef("none");
case call32:
return StringRef("call32");
case ripRel32:
return StringRef("ripRel32");
case gotLoad32:
return StringRef("gotLoad32");
case gotUse32:
return StringRef("gotUse32");
case pointer64:
return StringRef("pointer64");
case lea32WasGot:
return StringRef("lea32WasGot");
case lazyTarget:
return StringRef("lazyTarget");
case lazyImm:
return StringRef("lazyImm");
case gotTarget:
return StringRef("gotTarget");
}
return StringRef("???");
assert(0 && "invalid x86_64 Reference kind");
return StringRef();
}
static const Mapping* mappingsForArch(WriterOptionsMachO::Architecture arch) {
switch ( arch ) {
case WriterOptionsMachO::arch_x86_64:
return sKindMappingsx86_64;
case WriterOptionsMachO::arch_x86:
case WriterOptionsMachO::arch_arm:
assert(0 && "references table not yet implemented for arch");
return nullptr;
bool KindHandler_x86_64::isCallSite(Kind kind) {
return (kind == call32);
}
bool KindHandler_x86_64::isPointer(Kind kind) {
return (kind == pointer64);
}
bool KindHandler_x86_64::isLazyImmediate(Kind kind) {
return (kind == lazyImm);
}
bool KindHandler_x86_64::isLazyTarget(Kind kind) {
return (kind == lazyTarget);
}
void KindHandler_x86_64::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) {
int32_t *loc32 = reinterpret_cast<int32_t*>(location);
uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
switch ( (Kinds)kind ) {
case call32:
case ripRel32:
case gotLoad32:
case gotUse32:
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
break;
case pointer64:
*loc64 = targetAddress + addend;
break;
case lea32WasGot:
break;
case none:
case lazyTarget:
case lazyImm:
case gotTarget:
// do nothing
break;
}
}
bool ReferenceKind::isCallSite(WriterOptionsMachO::Architecture arch,
Reference::Kind kindValue) {
for (const Mapping* p = mappingsForArch(arch); p->string != NULL; ++p) {
if ( kindValue == p->value )
return (p->flags & flagsIsCallSite);
}
return false;
//===----------------------------------------------------------------------===//
// KindHandler_x86
//===----------------------------------------------------------------------===//
KindHandler_x86::~KindHandler_x86() {
}
bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
if ( kindValue == p->value )
return (p->flags & flags32RipRel);
Reference::Kind KindHandler_x86::stringToKind(StringRef str) {
if ( str.equals("none") )
return KindHandler_x86::none;
else if ( str.equals("call32") )
return KindHandler_x86::call32;
else if ( str.equals("abs32") )
return KindHandler_x86::abs32;
else if ( str.equals("pointer32") )
return KindHandler_x86::pointer32;
else if ( str.equals("lazyTarget") )
return KindHandler_x86::lazyTarget;
else if ( str.equals("lazyImm") )
return KindHandler_x86::lazyImm;
assert(0 && "invalid x86 Reference kind");
return 0;
}
StringRef KindHandler_x86::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) {
case none:
return StringRef("none");
case call32:
return StringRef("call32");
case abs32:
return StringRef("abs32");
case pointer32:
return StringRef("pointer32");
case lazyTarget:
return StringRef("lazyTarget");
case lazyImm:
return StringRef("lazyImm");
}
assert(0 && "invalid x86 Reference kind");
return StringRef();
}
bool KindHandler_x86::isCallSite(Kind kind) {
return (kind == call32);
}
bool KindHandler_x86::isPointer(Kind kind) {
return (kind == pointer32);
}
bool KindHandler_x86::isLazyImmediate(Kind kind) {
return (kind == lazyImm);
}
bool KindHandler_x86::isLazyTarget(Kind kind) {
return (kind == lazyTarget);
}
void KindHandler_x86::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) {
int32_t *loc32 = reinterpret_cast<int32_t*>(location);
switch ( (Kinds)kind ) {
case call32:
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
break;
case pointer32:
case abs32:
*loc32 = targetAddress + addend;
break;
case none:
case lazyTarget:
case lazyImm:
// do nothing
break;
}
return false;
}
//===----------------------------------------------------------------------===//
// KindHandler_arm
//===----------------------------------------------------------------------===//
KindHandler_arm::~KindHandler_arm() {
}
Reference::Kind KindHandler_arm::stringToKind(StringRef str) {
if ( str.equals("none") )
return KindHandler_arm::none;
else if ( str.equals("br22") )
return KindHandler_arm::br22;
else if ( str.equals("pointer32") )
return KindHandler_arm::pointer32;
else if ( str.equals("lazyTarget") )
return KindHandler_arm::lazyTarget;
else if ( str.equals("lazyImm") )
return KindHandler_arm::lazyImm;
assert(0 && "invalid ARM Reference kind");
return 0;
}
StringRef KindHandler_arm::kindToString(Reference::Kind kind) {
switch ( (Kinds)kind ) {
case none:
return StringRef("none");
case br22:
return StringRef("br22");
case pointer32:
return StringRef("pointer32");
case lazyTarget:
return StringRef("lazyTarget");
case lazyImm:
return StringRef("lazyImm");
}
assert(0 && "invalid ARM Reference kind");
return StringRef();
}
bool KindHandler_arm::isCallSite(Kind kind) {
return (kind == br22);
}
bool KindHandler_arm::isPointer(Kind kind) {
return (kind == pointer32);
}
bool KindHandler_arm::isLazyImmediate(Kind kind) {
return (kind == lazyImm);
}
bool KindHandler_arm::isLazyTarget(Kind kind) {
return (kind == lazyTarget);
}
void KindHandler_arm::applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) {
//int32_t *loc32 = reinterpret_cast<int32_t*>(location);
switch ( (Kinds)kind ) {
case br22:
// FIXME
break;
case pointer32:
// FIXME
break;
case none:
case lazyTarget:
case lazyImm:
// do nothing
break;
}
}
} // namespace mach_o
} // namespace lld

View File

@ -19,51 +19,104 @@ namespace lld {
namespace mach_o {
class ReferenceKind {
///
/// The KindHandler class is the abstract interface to Reference::Kind
/// values for mach-o files. Particular Kind values (e.g. 3) has a different
/// meaning for each architecture.
///
class KindHandler {
public:
// x86_64 Reference Kinds
enum {
x86_64_none = 0,
x86_64_call32 = 1,
x86_64_pcRel32 = 2,
x86_64_gotLoad32 = 3,
x86_64_gotUse32 = 4,
x86_64_lea32WasGot = 5,
x86_64_lazyTarget = 6,
x86_64_lazyImm = 7,
x86_64_gotTarget = 8,
x86_64_pointer64 = 9,
typedef Reference::Kind Kind;
static KindHandler *makeHandler(WriterOptionsMachO::Architecture arch);
virtual ~KindHandler();
virtual Kind stringToKind(StringRef str) = 0;
virtual StringRef kindToString(Kind) = 0;
virtual bool isCallSite(Kind) = 0;
virtual bool isPointer(Kind) = 0;
virtual bool isLazyImmediate(Kind) = 0;
virtual bool isLazyTarget(Kind) = 0;
virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress) = 0;
protected:
KindHandler();
};
class KindHandler_x86_64 : public KindHandler {
public:
enum Kinds {
none = 0,
call32 = 1,
ripRel32 = 2,
gotLoad32 = 3,
gotUse32 = 4,
lea32WasGot = 5,
lazyTarget = 6,
lazyImm = 7,
gotTarget = 8,
pointer64 = 9
};
// x86 Reference Kinds
enum {
x86_none = 0,
x86_call32 = 1,
x86_pointer32 = 2,
x86_lazyTarget = 3,
x86_lazyImm = 4,
virtual ~KindHandler_x86_64();
virtual Kind stringToKind(StringRef str);
virtual StringRef kindToString(Kind);
virtual bool isCallSite(Kind);
virtual bool isPointer(Kind);
virtual bool isLazyImmediate(Kind);
virtual bool isLazyTarget(Kind);
virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress);
};
class KindHandler_x86 : public KindHandler {
public:
enum Kinds {
none = 0,
call32 = 1,
abs32 = 2,
pointer32 = 3,
lazyTarget = 4,
lazyImm = 5
};
virtual ~KindHandler_x86();
virtual Kind stringToKind(StringRef str);
virtual StringRef kindToString(Kind);
virtual bool isCallSite(Kind);
virtual bool isPointer(Kind);
virtual bool isLazyImmediate(Kind);
virtual bool isLazyTarget(Kind);
virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress);
};
class KindHandler_arm : public KindHandler {
public:
enum Kinds {
none = 0,
br22 = 1,
pointer32 = 2,
lazyTarget = 3,
lazyImm = 4
// FIXME
};
// ARM Reference Kinds
enum {
arm_none = 0,
arm_br22 = 1,
arm_pointer32 = 2,
arm_lazyTarget = 3,
arm_lazyImm = 4,
// FIXME
};
virtual ~KindHandler_arm();
virtual Kind stringToKind(StringRef str);
virtual StringRef kindToString(Kind);
virtual bool isCallSite(Kind);
virtual bool isPointer(Kind);
virtual bool isLazyImmediate(Kind);
virtual bool isLazyTarget(Kind);
virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress);
static bool isCallSite(WriterOptionsMachO::Architecture arch,
Reference::Kind kindValue);
static bool isRipRel32(Reference::Kind kindValue);
static Reference::Kind fromString(StringRef kindName);
static StringRef toString(Reference::Kind kindValue);
};

View File

@ -19,183 +19,13 @@
#include "ReferenceKinds.h"
#include "SimpleAtoms.hpp"
#include "StubAtoms_x86_64.hpp"
#include "StubAtoms_x86.hpp"
namespace lld {
namespace mach_o {
//
// X86_64 Stub Atom created by the stubs pass.
//
class X86_64StubAtom : public SimpleDefinedAtom {
public:
X86_64StubAtom(const File &file, const Atom &lazyPointer)
: SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::x86_64_pcRel32, 2, &lazyPointer, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStub;
}
virtual uint64_t size() const {
return 6;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp *lazyPointer
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Stub Helper Common Atom created by the stubs pass.
//
class X86_64StubHelperCommonAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
: SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::x86_64_pcRel32, 3, &cache, 0);
this->addReference(ReferenceKind::x86_64_pcRel32, 11, &binder, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 16;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00, // leaq cache(%rip),%r11
0x41, 0x53, // push %r11
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *binder(%rip)
0x90 }; // nop
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Stub Helper Atom created by the stubs pass.
//
class X86_64StubHelperAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::x86_64_lazyImm, 1, nullptr, 0);
this->addReference(ReferenceKind::x86_64_pcRel32, 6, &helperCommon, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 10;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x68, 0x00, 0x00, 0x00, 0x00, // pushq $lazy-info-offset
0xE9, 0x00, 0x00, 0x00, 0x00 }; // jmp helperhelper
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Lazy Pointer Atom created by the stubs pass.
//
class X86_64LazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::x86_64_pointer64, 0, &helper, 0);
this->addReference(ReferenceKind::x86_64_lazyTarget, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeLazyPointer;
}
virtual uint64_t size() const {
return 8;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
return ArrayRef<uint8_t>(bytes, 8);
}
};
//
// X86_64 NonLazy (GOT) Pointer Atom created by the stubs pass.
//
class X86_64NonLazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64NonLazyPointerAtom(const File &file)
: SimpleDefinedAtom(file) {
}
X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::x86_64_pointer64, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeGOT;
}
virtual uint64_t size() const {
return 8;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
return ArrayRef<uint8_t>(bytes, 8);
}
};
//
// StubBinderAtom created by the stubs pass.
//

View File

@ -0,0 +1,201 @@
//===- lib/ReaderWriter/MachO/StubAtoms_x86.hpp ---------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_MACHO_STUB_ATOM_X86_H_
#define LLD_READER_WRITER_MACHO_STUB_ATOM_X86_H_
#include "llvm/ADT/ArrayRef.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
#include "ReferenceKinds.h"
#include "SimpleAtoms.hpp"
namespace lld {
namespace mach_o {
//
// X86 Stub Atom created by the stubs pass.
//
class X86StubAtom : public SimpleDefinedAtom {
public:
X86StubAtom(const File &file, const Atom &lazyPointer)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::abs32, 2, &lazyPointer, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStub;
}
virtual uint64_t size() const {
return 6;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp *lazyPointer
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86 Stub Helper Common Atom created by the stubs pass.
//
class X86StubHelperCommonAtom : public SimpleDefinedAtom {
public:
X86StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::abs32, 1, &cache, 0);
this->addReference(KindHandler_x86::abs32, 7, &binder, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 12;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind
0x90 }; // nop
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86 Stub Helper Atom created by the stubs pass.
//
class X86StubHelperAtom : public SimpleDefinedAtom {
public:
X86StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::lazyImm, 1, nullptr, 0);
this->addReference(KindHandler_x86::call32, 6, &helperCommon, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 10;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x68, 0x00, 0x00, 0x00, 0x00, // pushq $lazy-info-offset
0xE9, 0x00, 0x00, 0x00, 0x00 }; // jmp helperhelper
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86 Lazy Pointer Atom created by the stubs pass.
//
class X86LazyPointerAtom : public SimpleDefinedAtom {
public:
X86LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::pointer32, 0, &helper, 0);
this->addReference(KindHandler_x86::lazyTarget, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeLazyPointer;
}
virtual uint64_t size() const {
return 4;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] = { 0x00, 0x00, 0x00, 0x00 };
return ArrayRef<uint8_t>(bytes, 4);
}
};
//
// X86 NonLazy (GOT) Pointer Atom created by the stubs pass.
//
class X86NonLazyPointerAtom : public SimpleDefinedAtom {
public:
X86NonLazyPointerAtom(const File &file)
: SimpleDefinedAtom(file) {
}
X86NonLazyPointerAtom(const File &file, const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86::pointer32, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeGOT;
}
virtual uint64_t size() const {
return 4;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] = { 0x00, 0x00, 0x00, 0x0 };
return ArrayRef<uint8_t>(bytes, 4);
}
};
} // namespace mach_o
} // namespace lld
#endif // LLD_READER_WRITER_MACHO_STUB_ATOM_X86_H_

View File

@ -0,0 +1,204 @@
//===- lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp ------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_MACHO_STUB_ATOM_X86_64_H_
#define LLD_READER_WRITER_MACHO_STUB_ATOM_X86_64_H_
#include "llvm/ADT/ArrayRef.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
#include "ReferenceKinds.h"
#include "SimpleAtoms.hpp"
namespace lld {
namespace mach_o {
//
// X86_64 Stub Atom created by the stubs pass.
//
class X86_64StubAtom : public SimpleDefinedAtom {
public:
X86_64StubAtom(const File &file, const Atom &lazyPointer)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::ripRel32, 2, &lazyPointer, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStub;
}
virtual uint64_t size() const {
return 6;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp *lazyPointer
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Stub Helper Common Atom created by the stubs pass.
//
class X86_64StubHelperCommonAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::ripRel32, 3, &cache, 0);
this->addReference(KindHandler_x86_64::ripRel32, 11, &binder, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 16;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00, // leaq cache(%rip),%r11
0x41, 0x53, // push %r11
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *binder(%rip)
0x90 }; // nop
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Stub Helper Atom created by the stubs pass.
//
class X86_64StubHelperAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::lazyImm, 1, nullptr, 0);
this->addReference(KindHandler_x86_64::ripRel32, 6, &helperCommon, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeStubHelper;
}
virtual uint64_t size() const {
return 10;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permR_X;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t instructions[] =
{ 0x68, 0x00, 0x00, 0x00, 0x00, // pushq $lazy-info-offset
0xE9, 0x00, 0x00, 0x00, 0x00 }; // jmp helperhelper
assert(sizeof(instructions) == this->size());
return ArrayRef<uint8_t>(instructions, sizeof(instructions));
}
};
//
// X86_64 Lazy Pointer Atom created by the stubs pass.
//
class X86_64LazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::pointer64, 0, &helper, 0);
this->addReference(KindHandler_x86_64::lazyTarget, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeLazyPointer;
}
virtual uint64_t size() const {
return 8;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
return ArrayRef<uint8_t>(bytes, 8);
}
};
//
// X86_64 NonLazy (GOT) Pointer Atom created by the stubs pass.
//
class X86_64NonLazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64NonLazyPointerAtom(const File &file)
: SimpleDefinedAtom(file) {
}
X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
: SimpleDefinedAtom(file) {
this->addReference(KindHandler_x86_64::pointer64, 0, &shlib, 0);
}
virtual ContentType contentType() const {
return DefinedAtom::typeGOT;
}
virtual uint64_t size() const {
return 8;
}
virtual ContentPermissions permissions() const {
return DefinedAtom::permRW_;
}
virtual ArrayRef<uint8_t> rawContent() const {
static const uint8_t bytes[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
return ArrayRef<uint8_t>(bytes, 8);
}
};
} // namespace mach_o
} // namespace lld
#endif // LLD_READER_WRITER_MACHO_STUB_ATOM_X86_64_H_

View File

@ -28,7 +28,9 @@ namespace mach_o {
class StubsPass : public lld::StubsPass {
public:
StubsPass(const WriterOptionsMachO &options) : _options(options) {
StubsPass(const WriterOptionsMachO &options)
: _options(options),
_kindHandler(KindHandler::makeHandler(options.architecture())) {
}
virtual bool noTextRelocs() {
@ -36,7 +38,7 @@ public:
}
virtual bool isCallSite(Reference::Kind kind) {
return ReferenceKind::isCallSite(_options.architecture(), kind);
return _kindHandler->isCallSite(kind);
}
virtual const DefinedAtom* getStub(const Atom& target) {
@ -60,7 +62,8 @@ public:
case WriterOptionsMachO::arch_x86:
return makeStub_x86(target);
case WriterOptionsMachO::arch_arm:
case WriterOptionsMachO::arch_armv6:
case WriterOptionsMachO::arch_armv7:
return makeStub_arm(target);
}
}
@ -87,8 +90,24 @@ public:
}
const DefinedAtom* makeStub_x86(const Atom& target) {
assert(0 && "stubs not yet implemented for x86");
return nullptr;
if ( _helperCommonAtom == nullptr ) {
// Lazily create common helper code and data.
_helperCacheAtom = new X86NonLazyPointerAtom(_file);
_binderAtom = new StubBinderAtom(_file);
_helperBinderAtom = new X86NonLazyPointerAtom(_file, *_binderAtom);
_helperCommonAtom = new X86StubHelperCommonAtom(_file,
*_helperCacheAtom, *_helperBinderAtom);
}
const DefinedAtom* helper = new X86StubHelperAtom(_file,
*_helperCommonAtom);
_stubHelperAtoms.push_back(helper);
const DefinedAtom* lp = new X86LazyPointerAtom(_file, *helper, target);
assert(lp->contentType() == DefinedAtom::typeLazyPointer);
_lazyPointers.push_back(lp);
const DefinedAtom* stub = new X86StubAtom(_file, *lp);
assert(stub->contentType() == DefinedAtom::typeStub);
_targetToStub[&target] = stub;
return stub;
}
const DefinedAtom* makeStub_arm(const Atom& target) {
@ -127,6 +146,7 @@ private:
};
const WriterOptionsMachO &_options;
KindHandler *_kindHandler;
File _file;
llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
std::vector<const DefinedAtom*> _lazyPointers;

View File

@ -129,10 +129,6 @@ private:
const WriterOptionsMachO &options,
class MachOWriter &writer);
void applyFixup(Reference::Kind kind, uint64_t addend,
uint8_t* location, uint64_t fixupAddress,
uint64_t targetAddress);
StringRef _segmentName;
StringRef _sectionName;
const WriterOptionsMachO &_options;
@ -206,6 +202,7 @@ private:
segment_command *_linkEditSegment;
symtab_command *_symbolTableLoadCommand;
entry_point_command *_entryPointLoadCommand;
thread_command *_threadLoadCommand;
dyld_info_command *_dyldInfoLoadCommand;
std::vector<load_command*> _loadCmds;
std::vector<ChunkSegInfo> _sectionInfo;
@ -354,11 +351,14 @@ public:
uint64_t *segStartAddr, uint64_t *segEndAddr);
const std::vector<Chunk*> chunks() { return _chunks; }
KindHandler *kindHandler() { return _referenceKindHandler; }
bool use64BitMachO() const;
private:
friend class LoadCommandsChunk;
friend class LazyBindingInfoChunk;
friend class BindingInfoChunk;
void build(const lld::File &file);
void createChunks(const lld::File &file);
@ -373,6 +373,7 @@ private:
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
const WriterOptionsMachO &_options;
KindHandler *_referenceKindHandler;
StubsPass _stubsPass;
GOTPass _gotPass;
CRuntimeFile _cRuntimeFile;
@ -386,7 +387,7 @@ private:
LazyBindingInfoChunk *_lazyBindingInfo;
SymbolTableChunk *_symbolTableChunk;
SymbolStringsChunk *_stringsChunk;
const DefinedAtom *_mainAtom;
const DefinedAtom *_entryAtom;
uint64_t _linkEditStartOffset;
uint64_t _linkEditStartAddress;
};
@ -582,34 +583,13 @@ void SectionChunk::write(uint8_t *chunkBuffer) {
if ( ref->target() != nullptr )
targetAddress = _writer.addressOfAtom(ref->target());
uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
this->applyFixup(ref->kind(), ref->addend(), &atomContent[offset],
fixupAddress, targetAddress);
_writer.kindHandler()->applyFixup(ref->kind(), ref->addend(),
&atomContent[offset], fixupAddress, targetAddress);
}
}
}
void SectionChunk::applyFixup(Reference::Kind kind, uint64_t addend,
uint8_t* location, uint64_t fixupAddress,
uint64_t targetAddress) {
//fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
// "fixupAddress=0x%0llX, targetAddress=0x%0llX\n",
// kindToString(kind).data(), addend,
// fixupAddress, targetAddress);
if ( ReferenceKind::isRipRel32(kind) ) {
// compute rip relative value and update.
int32_t* loc32 = reinterpret_cast<int32_t*>(location);
*loc32 = (targetAddress - (fixupAddress+4)) + addend;
}
else if ( kind == ReferenceKind::x86_64_pointer64 ) {
uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
*loc64 = targetAddress + addend;
}
}
//===----------------------------------------------------------------------===//
// MachHeaderChunk
//===----------------------------------------------------------------------===//
@ -687,7 +667,8 @@ LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh,
MachOWriter& writer)
: _mh(mh), _options(options), _writer(writer),
_linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr),
_entryPointLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) {
_entryPointLoadCommand(nullptr), _threadLoadCommand(nullptr),
_dyldInfoLoadCommand(nullptr) {
}
@ -815,15 +796,19 @@ void LoadCommandsChunk::computeSize(const lld::File &file) {
this->addLoadCommand(_dyldInfoLoadCommand);
// Add entry point load command to main executables
if (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable) {
if ( _options.addEntryPointLoadCommand() ) {
_entryPointLoadCommand = new entry_point_command(is64);
this->addLoadCommand(_entryPointLoadCommand);
}
else if ( _options.addUnixThreadLoadCommand() ) {
_threadLoadCommand = new thread_command(_options.cpuType(), is64);
this->addLoadCommand(_threadLoadCommand);
}
// Compute total size.
_size = _mh.loadCommandsSize();
}
void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
// Update segment/section information in segment load commands
@ -887,11 +872,17 @@ void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
// Update entry point
if ( _entryPointLoadCommand != nullptr ) {
const Atom *mainAtom = _writer._mainAtom;
const Atom *mainAtom = _writer._entryAtom;
assert(mainAtom != nullptr);
uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
_entryPointLoadCommand->entryoff = entryOffset;
}
else if ( _threadLoadCommand != nullptr ) {
const Atom *startAtom = _writer._entryAtom;
assert(startAtom != nullptr);
_threadLoadCommand->setPC(_writer.addressOfAtom(startAtom));
}
}
@ -1037,9 +1028,9 @@ void BindingInfoChunk::computeSize(const lld::File &file,
const SharedLibraryAtom *shlTarget
= dyn_cast<SharedLibraryAtom>(target);
if ( shlTarget != nullptr ) {
assert(ref->kind() == ReferenceKind::x86_64_pointer64);
assert(_writer.kindHandler()->isPointer(ref->kind()));
targetName = shlTarget->name();
ordinal = 1;
ordinal = 1; // FIXME
}
}
}
@ -1096,15 +1087,22 @@ const char* LazyBindingInfoChunk::info() {
return "lazy binding info";
}
//
// Called when lazy-binding-info is being laid out in __LINKEDIT. We need
// to find the helper atom which contains the instruction which loads an
// immediate value that is the offset into the lazy-binding-info, and set
// that immediate value to be the offset parameter.
void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
uint32_t offset) {
for (const Reference *ref : *lazyPointerAtom ) {
if ( ref->kind() != ReferenceKind::x86_64_pointer64 )
if ( ! _writer.kindHandler()->isPointer(ref->kind() ) )
continue;
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(ref->target());
const Atom *targ = ref->target();
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(targ);
assert(helperAtom != nullptr);
// Found helper atom. Search it for Reference that is lazy immediate value.
for (const Reference *href : *helperAtom ) {
if ( href->kind() == ReferenceKind::x86_64_lazyImm ) {
if ( _writer.kindHandler()->isLazyImmediate(href->kind()) ) {
(const_cast<Reference*>(href))->setAddend(offset);
return;
}
@ -1154,7 +1152,7 @@ void LazyBindingInfoChunk::computeSize(const lld::File &file,
int flags = 0;
StringRef name;
for (const Reference *ref : *lazyPointerAtom ) {
if ( ref->kind() == ReferenceKind::x86_64_lazyTarget ) {
if ( _writer.kindHandler()->isLazyTarget(ref->kind()) ) {
const Atom *shlib = ref->target();
assert(shlib != nullptr);
name = shlib->name();
@ -1298,9 +1296,11 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
//===----------------------------------------------------------------------===//
MachOWriter::MachOWriter(const WriterOptionsMachO &options)
: _options(options), _stubsPass(options), _cRuntimeFile(options),
: _options(options),
_referenceKindHandler(KindHandler::makeHandler(_options.architecture())),
_stubsPass(options), _cRuntimeFile(options),
_bindingInfo(nullptr), _lazyBindingInfo(nullptr),
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _mainAtom(nullptr),
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr),
_linkEditStartOffset(0), _linkEditStartAddress(0) {
}
@ -1388,16 +1388,16 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
void MachOWriter::buildAtomToAddressMap() {
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< "assign atom addresses:\n");
const bool lookForMain =
const bool lookForEntry =
(_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable);
for (SectionChunk *chunk : _sectionChunks ) {
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
if ( lookForMain
if ( lookForEntry
&& (info.atom->contentType() == DefinedAtom::typeCode)
&& (info.atom->size() != 0)
&& info.atom->name().equals("_main") ) {
_mainAtom = info.atom;
&& info.atom->name().equals(_options.entryPointName()) ) {
_entryAtom = info.atom;
}
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< " address="
@ -1544,23 +1544,10 @@ void MachOWriter::addFiles(InputFiles &inputFiles) {
} // namespace mach_o
Writer* createWriterMachO(const WriterOptionsMachO &options) {
return new lld::mach_o::MachOWriter(options);
}
WriterOptionsMachO::WriterOptionsMachO()
: _outputkind(outputDynamicExecutable),
_archName("x86_64"),
_architecture(arch_x86_64),
_pageZeroSize(0x100000000),
_cpuType(mach_o::CPU_TYPE_X86_64),
_cpuSubtype(mach_o::CPU_SUBTYPE_X86_64_ALL),
_noTextRelocations(true) {
}
WriterOptionsMachO::~WriterOptionsMachO() {
}
} // namespace lld

View File

@ -0,0 +1,144 @@
//===- lib/ReaderWriter/MachO/WriterOptionsMachO.cpp ----------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/WriterMachO.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/system_error.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "MachOFormat.hpp"
namespace lld {
WriterOptionsMachO::WriterOptionsMachO()
: _outputkind(outputDynamicExecutable),
_architecture(arch_x86),
_pageZeroSize(0x1000),
_noTextRelocations(true) {
}
WriterOptionsMachO::~WriterOptionsMachO() {
}
StringRef WriterOptionsMachO::archName() const {
switch ( _architecture ) {
case arch_x86_64:
return StringRef("x86_64");
case arch_x86:
return StringRef("i386");
case arch_armv6:
return StringRef("armv6");
case arch_armv7:
return StringRef("armv7");
}
assert(0 && "unknown arch");
return StringRef("???");
}
uint32_t WriterOptionsMachO::cpuType() const {
switch ( _architecture ) {
case arch_x86_64:
return mach_o::CPU_TYPE_X86_64;
case arch_x86:
return mach_o::CPU_TYPE_I386;
case arch_armv6:
case arch_armv7:
return mach_o::CPU_TYPE_ARM;
}
assert(0 && "unknown arch");
return 0;
}
uint32_t WriterOptionsMachO::cpuSubtype() const {
switch ( _architecture ) {
case arch_x86_64:
return mach_o::CPU_SUBTYPE_X86_64_ALL;
case arch_x86:
return mach_o::CPU_SUBTYPE_X86_ALL;
case arch_armv6:
return mach_o::CPU_SUBTYPE_ARM_V6;
case arch_armv7:
return mach_o::CPU_SUBTYPE_ARM_V7;
}
assert(0 && "unknown arch");
return 0;
}
uint64_t WriterOptionsMachO::pageZeroSize() const {
switch ( _outputkind ) {
case outputDynamicExecutable:
return _pageZeroSize;
case outputDylib:
case outputBundle:
case outputObjectFile:
assert(_pageZeroSize == 0);
return 0;
}
assert(0 && "unknown outputkind");
return 0;
}
bool WriterOptionsMachO::addEntryPointLoadCommand() const {
switch ( _outputkind ) {
case outputDynamicExecutable:
// Only main executables have an entry point
return false;
case outputDylib:
case outputBundle:
case outputObjectFile:
return false;
}
assert(0 && "unknown outputkind");
return false;
}
bool WriterOptionsMachO::addUnixThreadLoadCommand() const {
switch ( _outputkind ) {
case outputDynamicExecutable:
// Only main executables have an entry point
return true;
case outputDylib:
case outputBundle:
case outputObjectFile:
return false;
}
assert(0 && "unknown outputkind");
return false;
}
StringRef WriterOptionsMachO::entryPointName() const {
switch ( _outputkind ) {
case outputDynamicExecutable:
// Only main executables have an entry point
if ( ! _customEntryPointName.empty() ) {
return _customEntryPointName;
}
else {
if ( true || this->addEntryPointLoadCommand() )
return StringRef("_main");
else
return StringRef("start");
}
break;
case outputDylib:
case outputBundle:
case outputObjectFile:
return StringRef();
}
assert(0 && "unknown outputkind");
return StringRef();
}
} // namespace lld

View File

@ -196,7 +196,6 @@ public:
<< spacePadding(strlen("scope"))
<< KeyValues::scope(atom.scope())
<< "\n";
hasDash = true;
}
if ( atom.interposable() != KeyValues::interposableDefault ) {