[llvm-commits] [lld] r158336 - in /lld/trunk: include/lld/ReaderWriter/WriterMachO.h lib/ReaderWriter/MachO/CMakeLists.txt lib/ReaderWriter/MachO/MachOFormat.hpp lib/ReaderWriter/MachO/ReferenceKinds.cpp lib/ReaderWriter/MachO/ReferenceKinds.h li

Nick Kledzik kledzik at apple.com
Mon Jun 11 17:19:49 PDT 2012


On Jun 11, 2012, at 4:02 PM, Chandler Carruth wrote:

> On Mon, Jun 11, 2012 at 3:53 PM, Nick Kledzik <kledzik at apple.com> wrote:
> Author: kledzik
> Date: Mon Jun 11 17:53:15 2012
> New Revision: 158336
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=158336&view=rev
> Log:
> 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.
> 
> This really feels like it should be split across separate commits to make code review more tractable Nick...
> 
> You have several changes which are no-functionality changed, just moving code around. Those should always be separate. They can be reviewed super easily, and that allows the commits which actually make changes to be reviewed with a precise diff.
> 
> You actually have the different steps in your log message: each sentence feels like it should have been its own distinct commit.
> 
> 
> For reference, I mention this because several people have come to me expressing interest in getting involved with lld, but have struggled to review the existing code and start reviewing commits because the commits were very lumped together.

I understand simple, modular commits for a mature, large code base with lots of developers involved.

But, lld is still very much in its infancy.  These commits are more like check-points.   I expect plenty more refactoring churn before lld is stable enough to open it up to more contributors. 

That said, if there are developers interested in lld, I'd very much like to hear what design areas they would like documented better.  Questions like: How would X be handled by an in-memory based linker?  or How does the Atom model handle a cpu with feature X, etc.   Getting me to document  those design points will help everyone come up to speed and see how their needs fit into the lld model, and ensure lld can support (eventually) everyone's linking needs.

-Nick


> 
> Added:
>    lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86.hpp
>    lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp
>    lld/trunk/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp
> Modified:
>    lld/trunk/include/lld/ReaderWriter/WriterMachO.h
>    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
>    lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
>    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
>    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
>    lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp
>    lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp
>    lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
>    lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp
> 
> Modified: lld/trunk/include/lld/ReaderWriter/WriterMachO.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterMachO.h?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/WriterMachO.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/WriterMachO.h Mon Jun 11 17:53:15 2012
> @@ -51,25 +51,27 @@
>   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;
>  };
> 
> 
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Mon Jun 11 17:53:15 2012
> @@ -1,4 +1,5 @@
>  add_lld_library(lldMachO
>   WriterMachO.cpp
> +  WriterOptionsMachO.cpp
>   ReferenceKinds.cpp
>   )
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp Mon Jun 11 17:53:15 2012
> @@ -131,7 +131,7 @@
> 
>  };
> 
> -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 @@
>  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 @@
>  };
> 
> 
> +//
> +// 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
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp Mon Jun 11 17:53:15 2012
> @@ -16,85 +16,299 @@
>  namespace lld {
>  namespace mach_o {
> 
> -
> -struct Mapping {
> -  const char*           string;
> -  Reference::Kind       value;
> -  uint32_t              flags;
> -};
> -
> -enum {
> -  flagsNone       = 0x0000,
> -  flagsIsCallSite = 0x0001,
> -  flagsUsesGOT    = 0x0002,
> -  flagsisGOTLoad  = 0x0006,
> -  flags32RipRel   = 0x1000,
> -};
> -
> -
> -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::KindHandler() {
> +}
> +
> +KindHandler::~KindHandler() {
> +}
> +
> +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;
> -  }
> -  return StringRef("???");
> +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");
> +  }
> +  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;
> +  }
> +}
> +
> +
> +//===----------------------------------------------------------------------===//
> +//  KindHandler_x86
> +//===----------------------------------------------------------------------===//
> +
> +KindHandler_x86::~KindHandler_x86() {
> +}
> +
> +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 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);
> +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;
>  }
> 
> -bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
> -  for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
> -    if ( kindValue == p->value )
> -      return (p->flags & flags32RipRel);
> +
> +//===----------------------------------------------------------------------===//
> +//  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");
>   }
> -  return false;
> +  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
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h Mon Jun 11 17:53:15 2012
> @@ -19,51 +19,104 @@
>  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,
> -    // FIXME
> +  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
>   };
> 
> -  // ARM Reference Kinds
> - enum {
> -    arm_none        = 0,
> -    arm_br22        = 1,
> -    arm_pointer32   = 2,
> -    arm_lazyTarget  = 3,
> -    arm_lazyImm     = 4,
> +  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
>   };
> 
> -  static bool isCallSite(WriterOptionsMachO::Architecture arch,
> -                                                    Reference::Kind kindValue);
> -
> -  static bool isRipRel32(Reference::Kind kindValue);
> +  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 Reference::Kind fromString(StringRef kindName);
> -  static StringRef toString(Reference::Kind kindValue);
> -
>  };
> 
> 
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp Mon Jun 11 17:53:15 2012
> @@ -19,184 +19,14 @@
> 
>  #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.
>  //
>  class StubBinderAtom : public SharedLibraryAtom {
> 
> Added: lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86.hpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86.hpp?rev=158336&view=auto
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86.hpp (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86.hpp Mon Jun 11 17:53:15 2012
> @@ -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_
> 
> Added: lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp?rev=158336&view=auto
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp Mon Jun 11 17:53:15 2012
> @@ -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_
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp Mon Jun 11 17:53:15 2012
> @@ -28,7 +28,9 @@
> 
>  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 @@
>   }
> 
>   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 @@
>       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 @@
>   }
> 
>   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 @@
>   };
> 
>   const WriterOptionsMachO                       &_options;
> +  KindHandler                                    *_kindHandler;
>   File                                            _file;
>   llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
>   std::vector<const DefinedAtom*>                 _lazyPointers;
> 
> Modified: lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp Mon Jun 11 17:53:15 2012
> @@ -129,10 +129,6 @@
>                              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 @@
>   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 @@
>                                 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 @@
>   typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
> 
>   const WriterOptionsMachO   &_options;
> +  KindHandler                *_referenceKindHandler;
>   StubsPass                   _stubsPass;
>   GOTPass                     _gotPass;
>   CRuntimeFile                _cRuntimeFile;
> @@ -386,7 +387,7 @@
>   LazyBindingInfoChunk       *_lazyBindingInfo;
>   SymbolTableChunk           *_symbolTableChunk;
>   SymbolStringsChunk         *_stringsChunk;
> -  const DefinedAtom          *_mainAtom;
> +  const DefinedAtom          *_entryAtom;
>   uint64_t                    _linkEditStartOffset;
>   uint64_t                    _linkEditStartAddress;
>  };
> @@ -582,34 +583,13 @@
>       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 @@
>                                      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 @@
>   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 @@
> 
>   // 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 @@
>           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 @@
>   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 @@
>       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 @@
>  //===----------------------------------------------------------------------===//
> 
>  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::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 @@
> 
>  } // 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
> 
> 
> Added: lld/trunk/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp?rev=158336&view=auto
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp Mon Jun 11 17:53:15 2012
> @@ -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
> +
> 
> Modified: lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp?rev=158336&r1=158335&r2=158336&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp Mon Jun 11 17:53:15 2012
> @@ -196,7 +196,6 @@
>             << spacePadding(strlen("scope"))
>             << KeyValues::scope(atom.scope())
>             << "\n";
> -      hasDash = true;
>     }
> 
>      if ( atom.interposable() != KeyValues::interposableDefault ) {
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120611/4f814409/attachment.html>


More information about the llvm-commits mailing list