[llvm-commits] [llvm] r128031 - in /llvm/trunk: include/llvm/ExecutionEngine/RuntimeDyld.h lib/ExecutionEngine/Makefile lib/ExecutionEngine/RuntimeDyld/ lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt lib/ExecutionEngine/RuntimeDyld/Makefile lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp tools/llvm-rtdyld/Makefile tools/llvm-rtdyld/llvm-rtdyld.cpp

Jim Grosbach grosbach at apple.com
Tue Mar 22 13:32:34 PDT 2011


That depends on what you're looking to do. What specifically do you mean by supporting ELF? The code should work as-is on an ELF based system. It just needs the input object file to be a MachO.

Even as this gets fleshed out to handle more things, it's only at the edges where the JITed code interfaces with external bits that there's likely to be any extra work required to run on an ELF based system, and that should be relatively self-contained.

So if you mean whether this infrastructure should work on an ELF based host, then yes, at least most of it should work without modification. If you mean using ELF as a container instead of MachO, then no, I have no plans to do that.

-Jim

On Mar 22, 2011, at 1:04 PM, Jan Sjodin wrote:

> Are you planning to add support for ELF also?
> 
> - Jan
> 
> From: Jim Grosbach <grosbach at apple.com>
> To: llvm-commits at cs.uiuc.edu
> Sent: Mon, March 21, 2011 6:15:52 PM
> Subject: [llvm-commits] [llvm] r128031 - in /llvm/trunk: include/llvm/ExecutionEngine/RuntimeDyld.h lib/ExecutionEngine/Makefile lib/ExecutionEngine/RuntimeDyld/ lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt lib/ExecutionEngine/RuntimeDyld/Makefile lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp tools/llvm-rtdyld/Makefile tools/llvm-rtdyld/llvm-rtdyld.cpp
> 
> Author: grosbach
> Date: Mon Mar 21 17:15:52 2011
> New Revision: 128031
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=128031&view=rev
> Log:
> Library-ize the dyld components of llvm-rtdyld.
> 
> Move the dynamic linking functionality of the llvm-rtdyld program into an
> ExecutionEngine support library. Update llvm-rtdyld to just load an object
> file into memory, use the library to process it, then run the _main()
> function, if one is found.
> 
> 
> Added:
>     llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Makefile
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> Modified:
>     llvm/trunk/lib/ExecutionEngine/Makefile
>     llvm/trunk/tools/llvm-rtdyld/Makefile
>     llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp
> 
> Added: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=128031&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (added)
> +++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Mon Mar 21 17:15:52 2011
> @@ -0,0 +1,45 @@
> +//===-- RuntimeDyld.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===//
> +//
> +//                    The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// Interface for the runtime dynamic linker facilities of the MC-JIT.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_RUNTIME_DYLD_H
> +#define LLVM_RUNTIME_DYLD_H
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Support/Memory.h"
> +
> +namespace llvm {
> +
> +class RuntimeDyldImpl;
> +class MemoryBuffer;
> +
> +class RuntimeDyld {
> +  RuntimeDyld(const RuntimeDyld &);    // DO NOT IMPLEMENT
> +  void operator=(const RuntimeDyld &);  // DO NOT IMPLEMENT
> +
> +  // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
> +  // interface.
> +  RuntimeDyldImpl *Dyld;
> +public:
> +  RuntimeDyld();
> +  ~RuntimeDyld();
> +
> +  bool loadObject(MemoryBuffer *InputBuffer);
> +  void *getSymbolAddress(StringRef Name);
> +  // FIXME: Should be parameterized to get the memory block associated with
> +  // a particular loaded object.
> +  sys::MemoryBlock getMemoryBlock();
> +};
> +
> +} // end namespace llvm
> +
> +#endif
> 
> Modified: llvm/trunk/lib/ExecutionEngine/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Makefile?rev=128031&r1=128030&r2=128031&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Makefile (original)
> +++ llvm/trunk/lib/ExecutionEngine/Makefile Mon Mar 21 17:15:52 2011
> @@ -8,6 +8,6 @@
> ##===----------------------------------------------------------------------===##
> LEVEL = ../..
> LIBRARYNAME = LLVMExecutionEngine
> -PARALLEL_DIRS = Interpreter JIT MCJIT
> +PARALLEL_DIRS = Interpreter JIT MCJIT RuntimeDyld
> 
> include $(LEVEL)/Makefile.common
> 
> Added: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt?rev=128031&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt Mon Mar 21 17:15:52 2011
> @@ -0,0 +1,3 @@
> +add_llvm_library(LLVMRuntimeDyld
> +  RuntimeDyld.cpp
> +  )
> 
> Added: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Makefile?rev=128031&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Makefile (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Makefile Mon Mar 21 17:15:52 2011
> @@ -0,0 +1,13 @@
> +##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===##
> +#
> +#                    The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL = ../../..
> +LIBRARYNAME = LLVMRuntimeDyld
> +
> +include $(LEVEL)/Makefile.common
> 
> Added: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=128031&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Mon Mar 21 17:15:52 2011
> @@ -0,0 +1,329 @@
> +//===-- RuntimeDyld.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===//
> +//
> +//                    The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// Implementation of the MC-JIT runtime dynamic linker.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/ExecutionEngine/RuntimeDyld.h"
> +#include "llvm/Object/MachOObject.h"
> +#include "llvm/Support/Memory.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/system_error.h"
> +using namespace llvm;
> +using namespace llvm::object;
> +
> +namespace llvm {
> +class RuntimeDyldImpl {
> +  // Master symbol table. As modules are loaded and external symbols are
> +  // resolved, their addresses are stored here.
> +  StringMap<void*> SymbolTable;
> +
> +  // FIXME: Should have multiple data blocks, one for each loaded chunk of
> +  //        compiled code.
> +  sys::MemoryBlock Data;
> +
> +  bool HasError;
> +  std::string ErrorStr;
> +
> +  // Set the error state and record an error string.
> +  bool Error(const Twine &Msg) {
> +    ErrorStr = Msg.str();
> +    HasError = true;
> +    return true;
> +  }
> +
> +  bool loadSegment32(const MachOObject *Obj,
> +                    const MachOObject::LoadCommandInfo *SegmentLCI,
> +                    const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
> +  bool loadSegment64(const MachOObject *Obj,
> +                    const MachOObject::LoadCommandInfo *SegmentLCI,
> +                    const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
> +
> +public:
> +  bool loadObject(MemoryBuffer *InputBuffer);
> +
> +  void *getSymbolAddress(StringRef Name) {
> +    // Use lookup() rather than [] because we don't want to add an entry
> +    // if there isn't one already, which the [] operator does.
> +    return SymbolTable.lookup(Name);
> +  }
> +
> +  sys::MemoryBlock getMemoryBlock() { return Data; }
> +
> +  // Is the linker in an error state?
> +  bool hasError() { return HasError; }
> +
> +  // Mark the error condition as handled and continue.
> +  void clearError() { HasError = false; }
> +
> +  // Get the error message.
> +  StringRef getErrorString() { return ErrorStr; }
> +};
> +
> +
> +
> +bool RuntimeDyldImpl::
> +loadSegment32(const MachOObject *Obj,
> +              const MachOObject::LoadCommandInfo *SegmentLCI,
> +              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
> +  InMemoryStruct<macho::SegmentLoadCommand> Segment32LC;
> +  Obj->ReadSegmentLoadCommand(*SegmentLCI, Segment32LC);
> +  if (!Segment32LC)
> +    return Error("unable to load segment load command");
> +
> +  // Map the segment into memory.
> +  std::string ErrorStr;
> +  Data = sys::Memory::AllocateRWX(Segment32LC->VMSize, 0, &ErrorStr);
> +  if (!Data.base())
> +    return Error("unable to allocate memory block: '" + ErrorStr + "'");
> +  memcpy(Data.base(), Obj->getData(Segment32LC->FileOffset,
> +                                  Segment32LC->FileSize).data(),
> +        Segment32LC->FileSize);
> +  memset((char*)Data.base() + Segment32LC->FileSize, 0,
> +        Segment32LC->VMSize - Segment32LC->FileSize);
> +
> +  // Bind the section indices to address.
> +  void **SectionBases = new void*[Segment32LC->NumSections];
> +  for (unsigned i = 0; i != Segment32LC->NumSections; ++i) {
> +    InMemoryStruct<macho::Section> Sect;
> +    Obj->ReadSection(*SegmentLCI, i, Sect);
> +    if (!Sect)
> +      return Error("unable to load section: '" + Twine(i) + "'");
> +
> +    // FIXME: We don't support relocations yet.
> +    if (Sect->NumRelocationTableEntries != 0)
> +      return Error("not yet implemented: relocations!");
> +
> +    // FIXME: Improve check.
> +    if (Sect->Flags != 0x80000400)
> +      return Error("unsupported section type!");
> +
> +    SectionBases[i] = (char*) Data.base() + Sect->Address;
> +  }
> +
> +  // Bind all the symbols to address.
> +  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
> +    InMemoryStruct<macho::SymbolTableEntry> STE;
> +    Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE);
> +    if (!STE)
> +      return Error("unable to read symbol: '" + Twine(i) + "'");
> +    if (STE->SectionIndex == 0)
> +      return Error("unexpected undefined symbol!");
> +
> +    unsigned Index = STE->SectionIndex - 1;
> +    if (Index >= Segment32LC->NumSections)
> +      return Error("invalid section index for symbol: '" + Twine() + "'");
> +
> +    // Get the symbol name.
> +    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
> +
> +    // Get the section base address.
> +    void *SectionBase = SectionBases[Index];
> +
> +    // Get the symbol address.
> +    void *Address = (char*) SectionBase + STE->Value;
> +
> +    // FIXME: Check the symbol type and flags.
> +    if (STE->Type != 0xF)
> +      return Error("unexpected symbol type!");
> +    if (STE->Flags != 0x0)
> +      return Error("unexpected symbol type!");
> +
> +    SymbolTable[Name] = Address;
> +  }
> +
> +  delete SectionBases;
> +  return false;
> +}
> +
> +
> +bool RuntimeDyldImpl::
> +loadSegment64(const MachOObject *Obj,
> +              const MachOObject::LoadCommandInfo *SegmentLCI,
> +              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
> +  InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
> +  Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC);
> +  if (!Segment64LC)
> +    return Error("unable to load segment load command");
> +
> +  // Map the segment into memory.
> +  std::string ErrorStr;
> +  Data = sys::Memory::AllocateRWX(Segment64LC->VMSize, 0, &ErrorStr);
> +  if (!Data.base())
> +    return Error("unable to allocate memory block: '" + ErrorStr + "'");
> +  memcpy(Data.base(), Obj->getData(Segment64LC->FileOffset,
> +                                  Segment64LC->FileSize).data(),
> +        Segment64LC->FileSize);
> +  memset((char*)Data.base() + Segment64LC->FileSize, 0,
> +        Segment64LC->VMSize - Segment64LC->FileSize);
> +
> +  // Bind the section indices to address.
> +  void **SectionBases = new void*[Segment64LC->NumSections];
> +  for (unsigned i = 0; i != Segment64LC->NumSections; ++i) {
> +    InMemoryStruct<macho::Section64> Sect;
> +    Obj->ReadSection64(*SegmentLCI, i, Sect);
> +    if (!Sect)
> +      return Error("unable to load section: '" + Twine(i) + "'");
> +
> +    // FIXME: We don't support relocations yet.
> +    if (Sect->NumRelocationTableEntries != 0)
> +      return Error("not yet implemented: relocations!");
> +
> +    // FIXME: Improve check.
> +    if (Sect->Flags != 0x80000400)
> +      return Error("unsupported section type!");
> +
> +    SectionBases[i] = (char*) Data.base() + Sect->Address;
> +  }
> +
> +  // Bind all the symbols to address.
> +  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
> +    InMemoryStruct<macho::Symbol64TableEntry> STE;
> +    Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
> +    if (!STE)
> +      return Error("unable to read symbol: '" + Twine(i) + "'");
> +    if (STE->SectionIndex == 0)
> +      return Error("unexpected undefined symbol!");
> +
> +    unsigned Index = STE->SectionIndex - 1;
> +    if (Index >= Segment64LC->NumSections)
> +      return Error("invalid section index for symbol: '" + Twine() + "'");
> +
> +    // Get the symbol name.
> +    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
> +
> +    // Get the section base address.
> +    void *SectionBase = SectionBases[Index];
> +
> +    // Get the symbol address.
> +    void *Address = (char*) SectionBase + STE->Value;
> +
> +    // FIXME: Check the symbol type and flags.
> +    if (STE->Type != 0xF)
> +      return Error("unexpected symbol type!");
> +    if (STE->Flags != 0x0)
> +      return Error("unexpected symbol type!");
> +
> +    SymbolTable[Name] = Address;
> +  }
> +
> +  delete SectionBases;
> +  return false;
> +}
> +
> +
> +
> +bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {
> +  // If the linker is in an error state, don't do anything.
> +  if (hasError())
> +    return true;
> +  // Load the Mach-O wrapper object.
> +  std::string ErrorStr;
> +  OwningPtr<MachOObject> Obj(
> +    MachOObject::LoadFromBuffer(InputBuffer, &ErrorStr));
> +  if (!Obj)
> +    return Error("unable to load object: '" + ErrorStr + "'");
> +
> +  // Validate that the load commands match what we expect.
> +  const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
> +    *DysymtabLCI = 0;
> +  for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
> +    const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
> +    switch (LCI.Command.Type) {
> +    case macho::LCT_Segment:
> +    case macho::LCT_Segment64:
> +      if (SegmentLCI)
> +        return Error("unexpected input object (multiple segments)");
> +      SegmentLCI = &LCI;
> +      break;
> +    case macho::LCT_Symtab:
> +      if (SymtabLCI)
> +        return Error("unexpected input object (multiple symbol tables)");
> +      SymtabLCI = &LCI;
> +      break;
> +    case macho::LCT_Dysymtab:
> +      if (DysymtabLCI)
> +        return Error("unexpected input object (multiple symbol tables)");
> +      DysymtabLCI = &LCI;
> +      break;
> +    default:
> +      return Error("unexpected input object (unexpected load command");
> +    }
> +  }
> +
> +  if (!SymtabLCI)
> +    return Error("no symbol table found in object");
> +  if (!SegmentLCI)
> +    return Error("no symbol table found in object");
> +
> +  // Read and register the symbol table data.
> +  InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
> +  Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
> +  if (!SymtabLC)
> +    return Error("unable to load symbol table load command");
> +  Obj->RegisterStringTable(*SymtabLC);
> +
> +  // Read the dynamic link-edit information, if present (not present in static
> +  // objects).
> +  if (DysymtabLCI) {
> +    InMemoryStruct<macho::DysymtabLoadCommand> DysymtabLC;
> +    Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC);
> +    if (!DysymtabLC)
> +      return Error("unable to load dynamic link-exit load command");
> +
> +    // FIXME: We don't support anything interesting yet.
> +    if (DysymtabLC->LocalSymbolsIndex != 0)
> +      return Error("NOT YET IMPLEMENTED: local symbol entries");
> +    if (DysymtabLC->ExternalSymbolsIndex != 0)
> +      return Error("NOT YET IMPLEMENTED: non-external symbol entries");
> +    if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries)
> +      return Error("NOT YET IMPLEMENTED: undefined symbol entries");
> +  }
> +
> +  // Load the segment load command.
> +  if (SegmentLCI->Command.Type == macho::LCT_Segment) {
> +    if (loadSegment32(Obj.get(), SegmentLCI, SymtabLC))
> +      return true;
> +  } else {
> +    if (loadSegment64(Obj.get(), SegmentLCI, SymtabLC))
> +      return true;
> +  }
> +
> +  return false;
> +}
> +
> +
> +//===----------------------------------------------------------------------===//
> +// RuntimeDyld class implementation
> +RuntimeDyld::RuntimeDyld() {
> +  Dyld = new RuntimeDyldImpl;
> +}
> +
> +RuntimeDyld::~RuntimeDyld() {
> +  delete Dyld;
> +}
> +
> +bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
> +  return Dyld->loadObject(InputBuffer);
> +}
> +
> +void *RuntimeDyld::getSymbolAddress(StringRef Name) {
> +  return Dyld->getSymbolAddress(Name);
> +}
> +
> +sys::MemoryBlock RuntimeDyld::getMemoryBlock() {
> +  return Dyld->getMemoryBlock();
> +}
> +
> +} // end namespace llvm
> 
> Modified: llvm/trunk/tools/llvm-rtdyld/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/Makefile?rev=128031&r1=128030&r2=128031&view=diff
> ==============================================================================
> --- llvm/trunk/tools/llvm-rtdyld/Makefile (original)
> +++ llvm/trunk/tools/llvm-rtdyld/Makefile Mon Mar 21 17:15:52 2011
> @@ -18,6 +18,6 @@
> # early so we can set up LINK_COMPONENTS before including Makefile.rules
> include $(LEVEL)/Makefile.config
> 
> -LINK_COMPONENTS := $(TARGETS_TO_BUILD) support MC object
> +LINK_COMPONENTS := $(TARGETS_TO_BUILD) support MC object RuntimeDyld
> 
> include $(LLVM_SRC_ROOT)/Makefile.rules
> 
> Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=128031&r1=128030&r2=128031&view=diff
> ==============================================================================
> --- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original)
> +++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Mon Mar 21 17:15:52 2011
> @@ -13,6 +13,7 @@
> 
> #include "llvm/ADT/StringMap.h"
> #include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ExecutionEngine/RuntimeDyld.h"
> #include "llvm/Object/MachOObject.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/ManagedStatic.h"
> @@ -51,157 +52,6 @@
> }
> 
> /* *** */
> -static bool
> -loadSegment32(const MachOObject *Obj,
> -              sys::MemoryBlock &Data,
> -              const MachOObject::LoadCommandInfo *SegmentLCI,
> -              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC,
> -              StringMap<void*> &SymbolTable) {
> -  InMemoryStruct<macho::SegmentLoadCommand> Segment32LC;
> -  Obj->ReadSegmentLoadCommand(*SegmentLCI, Segment32LC);
> -  if (!Segment32LC)
> -    return Error("unable to load segment load command");
> -
> -  // Map the segment into memory.
> -  std::string ErrorStr;
> -  Data = sys::Memory::AllocateRWX(Segment32LC->VMSize, 0, &ErrorStr);
> -  if (!Data.base())
> -    return Error("unable to allocate memory block: '" + ErrorStr + "'");
> -  memcpy(Data.base(), Obj->getData(Segment32LC->FileOffset,
> -                                  Segment32LC->FileSize).data(),
> -        Segment32LC->FileSize);
> -  memset((char*)Data.base() + Segment32LC->FileSize, 0,
> -        Segment32LC->VMSize - Segment32LC->FileSize);
> -
> -  // Bind the section indices to address.
> -  void **SectionBases = new void*[Segment32LC->NumSections];
> -  for (unsigned i = 0; i != Segment32LC->NumSections; ++i) {
> -    InMemoryStruct<macho::Section> Sect;
> -    Obj->ReadSection(*SegmentLCI, i, Sect);
> -    if (!Sect)
> -      return Error("unable to load section: '" + Twine(i) + "'");
> -
> -    // FIXME: We don't support relocations yet.
> -    if (Sect->NumRelocationTableEntries != 0)
> -      return Error("not yet implemented: relocations!");
> -
> -    // FIXME: Improve check.
> -    if (Sect->Flags != 0x80000400)
> -      return Error("unsupported section type!");
> -
> -    SectionBases[i] = (char*) Data.base() + Sect->Address;
> -  }
> -
> -  // Bind all the symbols to address.
> -  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
> -    InMemoryStruct<macho::SymbolTableEntry> STE;
> -    Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE);
> -    if (!STE)
> -      return Error("unable to read symbol: '" + Twine(i) + "'");
> -    if (STE->SectionIndex == 0)
> -      return Error("unexpected undefined symbol!");
> -
> -    unsigned Index = STE->SectionIndex - 1;
> -    if (Index >= Segment32LC->NumSections)
> -      return Error("invalid section index for symbol: '" + Twine() + "'");
> -
> -    // Get the symbol name.
> -    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
> -
> -    // Get the section base address.
> -    void *SectionBase = SectionBases[Index];
> -
> -    // Get the symbol address.
> -    void *Address = (char*) SectionBase + STE->Value;
> -
> -    // FIXME: Check the symbol type and flags.
> -    if (STE->Type != 0xF)
> -      return Error("unexpected symbol type!");
> -    if (STE->Flags != 0x0)
> -      return Error("unexpected symbol type!");
> -
> -    SymbolTable[Name] = Address;
> -  }
> -
> -  delete SectionBases;
> -  return false;
> -}
> -
> -static bool
> -loadSegment64(const MachOObject *Obj,
> -              sys::MemoryBlock &Data,
> -              const MachOObject::LoadCommandInfo *SegmentLCI,
> -              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC,
> -              StringMap<void*> &SymbolTable) {
> -  InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
> -  Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC);
> -  if (!Segment64LC)
> -    return Error("unable to load segment load command");
> -
> -  // Map the segment into memory.
> -  std::string ErrorStr;
> -  Data = sys::Memory::AllocateRWX(Segment64LC->VMSize, 0, &ErrorStr);
> -  if (!Data.base())
> -    return Error("unable to allocate memory block: '" + ErrorStr + "'");
> -  memcpy(Data.base(), Obj->getData(Segment64LC->FileOffset,
> -                                  Segment64LC->FileSize).data(),
> -        Segment64LC->FileSize);
> -  memset((char*)Data.base() + Segment64LC->FileSize, 0,
> -        Segment64LC->VMSize - Segment64LC->FileSize);
> -
> -  // Bind the section indices to address.
> -  void **SectionBases = new void*[Segment64LC->NumSections];
> -  for (unsigned i = 0; i != Segment64LC->NumSections; ++i) {
> -    InMemoryStruct<macho::Section64> Sect;
> -    Obj->ReadSection64(*SegmentLCI, i, Sect);
> -    if (!Sect)
> -      return Error("unable to load section: '" + Twine(i) + "'");
> -
> -    // FIXME: We don't support relocations yet.
> -    if (Sect->NumRelocationTableEntries != 0)
> -      return Error("not yet implemented: relocations!");
> -
> -    // FIXME: Improve check.
> -    if (Sect->Flags != 0x80000400)
> -      return Error("unsupported section type!");
> -
> -    SectionBases[i] = (char*) Data.base() + Sect->Address;
> -  }
> -
> -  // Bind all the symbols to address.
> -  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
> -    InMemoryStruct<macho::Symbol64TableEntry> STE;
> -    Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
> -    if (!STE)
> -      return Error("unable to read symbol: '" + Twine(i) + "'");
> -    if (STE->SectionIndex == 0)
> -      return Error("unexpected undefined symbol!");
> -
> -    unsigned Index = STE->SectionIndex - 1;
> -    if (Index >= Segment64LC->NumSections)
> -      return Error("invalid section index for symbol: '" + Twine() + "'");
> -
> -    // Get the symbol name.
> -    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
> -
> -    // Get the section base address.
> -    void *SectionBase = SectionBases[Index];
> -
> -    // Get the symbol address.
> -    void *Address = (char*) SectionBase + STE->Value;
> -
> -    // FIXME: Check the symbol type and flags.
> -    if (STE->Type != 0xF)
> -      return Error("unexpected symbol type!");
> -    if (STE->Flags != 0x0)
> -      return Error("unexpected symbol type!");
> -
> -    SymbolTable[Name] = Address;
> -  }
> -
> -  delete SectionBases;
> -  return false;
> -}
> 
> static int executeInput() {
>   // Load the input memory buffer.
> @@ -209,94 +59,28 @@
>   if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
>     return Error("unable to read input: '" + ec.message() + "'");
> 
> -  // Load the Mach-O wrapper object.
> -  std::string ErrorStr;
> -  OwningPtr<MachOObject> Obj(
> -    MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
> -  if (!Obj)
> -    return Error("unable to load object: '" + ErrorStr + "'");
> -
> -  // Validate that the load commands match what we expect.
> -  const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
> -    *DysymtabLCI = 0;
> -  for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
> -    const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
> -    switch (LCI.Command.Type) {
> -    case macho::LCT_Segment:
> -    case macho::LCT_Segment64:
> -      if (SegmentLCI)
> -        return Error("unexpected input object (multiple segments)");
> -      SegmentLCI = &LCI;
> -      break;
> -    case macho::LCT_Symtab:
> -      if (SymtabLCI)
> -        return Error("unexpected input object (multiple symbol tables)");
> -      SymtabLCI = &LCI;
> -      break;
> -    case macho::LCT_Dysymtab:
> -      if (DysymtabLCI)
> -        return Error("unexpected input object (multiple symbol tables)");
> -      DysymtabLCI = &LCI;
> -      break;
> -    default:
> -      return Error("unexpected input object (unexpected load command");
> -    }
> -  }
> -
> -  if (!SymtabLCI)
> -    return Error("no symbol table found in object");
> -  if (!SegmentLCI)
> -    return Error("no symbol table found in object");
> -
> -  // Read and register the symbol table data.
> -  InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
> -  Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
> -  if (!SymtabLC)
> -    return Error("unable to load symbol table load command");
> -  Obj->RegisterStringTable(*SymtabLC);
> -
> -  // Read the dynamic link-edit information, if present (not present in static
> -  // objects).
> -  if (DysymtabLCI) {
> -    InMemoryStruct<macho::DysymtabLoadCommand> DysymtabLC;
> -    Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC);
> -    if (!DysymtabLC)
> -      return Error("unable to load dynamic link-exit load command");
> -
> -    // FIXME: We don't support anything interesting yet.
> -    if (DysymtabLC->LocalSymbolsIndex != 0)
> -      return Error("NOT YET IMPLEMENTED: local symbol entries");
> -    if (DysymtabLC->ExternalSymbolsIndex != 0)
> -      return Error("NOT YET IMPLEMENTED: non-external symbol entries");
> -    if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries)
> -      return Error("NOT YET IMPLEMENTED: undefined symbol entries");
> -  }
> +  // Instantiate a dynamic linker.
> +  RuntimeDyld Dyld;
> 
> -  // Load the segment load command.
> -  sys::MemoryBlock Data;
> -  StringMap<void*> SymbolTable;
> -  if (SegmentLCI->Command.Type == macho::LCT_Segment) {
> -    if (loadSegment32(Obj.get(), Data, SegmentLCI, SymtabLC, SymbolTable))
> -      return true;
> -  } else {
> -    if (loadSegment64(Obj.get(), Data, SegmentLCI, SymtabLC, SymbolTable))
> -      return true;
> -  }
> +  // Load the object file into it.
> +  if (Dyld.loadObject(InputBuffer.take()))
> +    return true;
> 
>   // Get the address of "_main".
> -  StringMap<void*>::iterator it = SymbolTable.find("_main");
> -  if (it == SymbolTable.end())
> +  void *MainAddress = Dyld.getSymbolAddress("_main");
> +  if (MainAddress == 0)
>     return Error("no definition for '_main'");
> 
>   // Invalidate the instruction cache.
> +  sys::MemoryBlock Data = Dyld.getMemoryBlock();
>   sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
> 
>   // Make sure the memory is executable.
> +  std::string ErrorStr;
>   if (!sys::Memory::setExecutable(Data, &ErrorStr))
>     return Error("unable to mark function executable: '" + ErrorStr + "'");
> 
>   // Dispatch to _main().
> -  void *MainAddress = it->second;
>   errs() << "loaded '_main' at: " << MainAddress << "\n";
> 
>   int (*Main)(int, const char**) =
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list