text:
using namespace llvm;
using namespace llvm::object;

namespace {

static inline
error_code check(error_code Err) {
  if (Err) {
    report_fatal_error(Err.message());
  }
  return Err;
}

template<class ELFT>
class DyldELFObject
  : public ELFObjectFile<ELFT> {
  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)

  typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
  typedef Elf_Sym_Impl<ELFT> Elf_Sym;
  typedef
    Elf_Rel_Impl<ELFT, false> Elf_Rel;
  typedef
    Elf_Rel_Impl<ELFT, true> Elf_Rela;

  typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr;

  typedef typename ELFDataTypeTypedefHelper<
          ELFT>::value_type addr_type;

public:
  DyldELFObject(MemoryBuffer *Wrapper, error_code &ec);

  void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
  void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);

  // Methods for type inquiry through isa, cast and dyn_cast
  static inline bool classof(const Binary *v) {
    return (isa<ELFObjectFile<ELFT> >(v)
            && classof(cast<ELFObjectFile
                <ELFT> >(v)));
  }
  static inline bool classof(
      const ELFObjectFile<ELFT> *v) {
    return v->isDyldType();
  }
};

template<class ELFT>
class ELFObjectImage : public ObjectImageCommon {
  protected:
    DyldELFObject<ELFT> *DyldObj;
    bool Registered;

  public:
    ELFObjectImage(ObjectBuffer *Input,
                 DyldELFObject<ELFT> *Obj)
    : ObjectImageCommon(Input, Obj),
      DyldObj(Obj),
      Registered(false) {}

    virtual ~ELFObjectImage() {
      if (Registered)
        deregisterWithDebugger();
    }

    // Subclasses can override these methods to update the image with loaded
    // addresses for sections and common symbols
    virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr)
    {
      DyldObj->updateSectionAddress(Sec, Addr);
    }

    virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr)
    {
      DyldObj->updateSymbolAddress(Sym, Addr);
    }

    virtual void registerWithDebugger()
    {
      JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
      Registered = true;
    }
    virtual void deregisterWithDebugger()
    {
      JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
    }
};

// The MemoryBuffer passed into this constructor is just a wrapper around the
// actual memory.  Ultimately, the Binary parent class will take ownership of
// this MemoryBuffer object but not the underlying memory.
template<class ELFT>
DyldELFObject<ELFT>::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec)
  : ELFObjectFile<ELFT>(Wrapper, ec) {
  this->isDyldELFObject = true;
}

template<class ELFT>
void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
                                               uint64_t Addr) {
  DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
  Elf_Shdr *shdr = const_cast<Elf_Shdr*>(
                          reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));

  // This assumes the address passed in matches the target address bitness
  // The template-based type cast handles everything else.
  shdr->sh_addr = static_cast<addr_type>(Addr);
}

template<class ELFT>
void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
                                              uint64_t Addr) {

  Elf_Sym *sym = const_cast<Elf_Sym*>(
    ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl()));

  // This assumes the address passed in matches the target address bitness
  // The template-based type cast handles everything else.
  sym->st_value = static_cast<addr_type>(Addr);
}

} // namespace

namespace llvm {

void RuntimeDyldELF::registerEHFrames() {
  if (!MemMgr)
    return;
  for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
    SID EHFrameSID = UnregisteredEHFrameSections[i];
    uint8_t *EHFrameAddr = Sections[EHFrameSID].Address;
    uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress;
    size_t EHFrameSize = Sections[EHFrameSID].Size;
    MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
    RegisteredEHFrameSections.push_back(EHFrameSID);
  }
  UnregisteredEHFrameSections.clear();
}

void RuntimeDyldELF::deregisterEHFrames() {
  if (!MemMgr)
    return;
  for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) {
    SID EHFrameSID = RegisteredEHFrameSections[i];
    uint8_t *EHFrameAddr = Sections[EHFrameSID].Address;
    uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress;
    size_t EHFrameSize = Sections[EHFrameSID].Size;
    MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
  }
  RegisteredEHFrameSections.clear();
}

ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
  if (Buffer->getBufferSize() < ELF::EI_NIDENT)
    llvm_unreachable("Unexpected ELF object size");
  std::pair<unsigned char, unsigned char> Ident = std::make_pair(
                         (uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS],
                         (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]);
  error_code ec;

  if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
    DyldELFObject<ELFType<support::little, 4, false> > *Obj =
      new DyldELFObject<ELFType<support::little, 4, false> >(
        Buffer->getMemBuffer(), ec);
    return new ELFObjectImage<ELFType<support::little, 4, false> >(Buffer, Obj);
  }
  else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
    DyldELFObject<ELFType<support::big, 4, false> > *Obj =
      new DyldELFObject<ELFType<support::big, 4, false> >(
        Buffer->getMemBuffer(), ec);
    return new ELFObjectImage<ELFType<support::big, 4, false> >(Buffer, Obj);
  }
  else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
    DyldELFObject<ELFType<support::big, 8, true> > *Obj =
      new DyldELFObject<ELFType<support::big, 8, true> >(
        Buffer->getMemBuffer(), ec);
    return new ELFObjectImage<ELFType<support::big, 8, true> >(Buffer, Obj);
  }
  else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
    DyldELFObject<ELFType<support::little, 8, true> > *Obj =
      new DyldELFObject<ELFType<support::little, 8, true> >(
        Buffer->getMemBuffer(), ec);
    return new ELFObjectImage<ELFType<support::little, 8, true> >(Buffer, Obj);
  }
  else
    llvm_unreachable("Unexpected ELF format");
}

RuntimeDyldELF::~RuntimeDyldELF() {
}

void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
                                             uint64_t Offset,
                                             uint64_t Value,
                                             uint32_t Type,
                                             int64_t  Addend,
                                             uint64_t SymOffset) {
  switch (Type) {
  default:
    llvm_unreachable("Relocation type not implemented yet!");
  break;
  case ELF::R_X86_64_64: {
    uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset);
    *Target = Value + Addend;
    DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend))
                 << " at " << format("%p\n",Target));
    break;
  }
  case ELF::R_X86_64_32:
  case ELF::R_X86_64_32S: {
    Value += Addend;
    assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) ||
           (Type == ELF::R_X86_64_32S &&
             ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN)));
    uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
    uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
    *Target = TruncatedAddr;
    DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr)
                 << " at " << format("%p\n",Target));
    break;
  }
  case ELF::R_X86_64_GOTPCREL: {
    // findGOTEntry returns the 'G + GOT' part of the relocation calculation
    // based on the load/target address of the GOT (not the current/local addr).
    uint64_t GOTAddr = findGOTEntry(Value, SymOffset);
    uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
    uint64_t  FinalAddress = Section.LoadAddress + Offset;
    // The processRelocationRef method combines the symbol offset and the addend
    // and in most cases that's what we want.  For this relocation type, we need
    // the raw addend, so we subtract the symbol offset to get it.
    int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress;
    assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
    int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
    *Target = TruncOffset;
    break;
  }
  case ELF::R_X86_64_PC32: {
    // Get the placeholder value from the generated object since
    // a previous relocation attempt may have overwritten the loaded version
    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
                                                                   + Offset);
    uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
    uint64_t  FinalAddress = Section.LoadAddress + Offset;
    int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
    assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
    int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
    *Target = TruncOffset;
    break;
  }
  case ELF::R_X86_64_PC64: {
    // Get the placeholder value from the generated object since
    // a previous relocation attempt may have overwritten the loaded version
    uint64_t *Placeholder = reinterpret_cast<uint64_t*>(Section.ObjAddress
                                                                   + Offset);
    uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset);
    uint64_t  FinalAddress = Section.LoadAddress + Offset;
    *Target = *Placeholder + Value + Addend - FinalAddress;
    break;
  }
  }
}

void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
                                          uint64_t Offset,
                                          uint32_t Value,
                                          uint32_t Type,
                                          int32_t Addend) {
  switch (Type) {
  case ELF::R_386_32: {
    // Get the placeholder value from the generated object since
    // a previous relocation attempt may have overwritten the loaded version
    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
                                                                   + Offset);
    uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
    *Target = *Placeholder + Value + Addend;
    break;
  }
  case ELF::R_386_PC32: {
    // Get the placeholder value from the generated object since
    // a previous relocation attempt may have overwritten the loaded version
    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress
                                                                   + Offset);
    uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
    uint32_t  FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
    uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
    *Target = RealOffset;
    break;
    }
    default:
      // There are other relocation types, but it appears these are the
      // only ones currently used by the LLVM ELF object writer
      llvm_unreachable("Relocation type not implemented yet!");
      break;
  }
}

void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
                                              uint64_t Offset,
                                              uint64_t Value,
                                              uint32_t Type,
                                              int64_t Addend) {
  uint32_t *TargetPtr = reinterpret_cast<uint32_t*>(Section.Address + Offset);
  uint64_t FinalAddress = Section.LoadAddress + Offset;

  DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x"
               << format("%llx", Section.Address + Offset)
               << " FinalAddress: 0x" << format("%llx",FinalAddress)
               << " Value: 0x" << format("%llx",Value)
               << " Type: 0x" << format("%x",Type)
               << " Addend: 0x" << format("%llx",Addend)
               << "\n");

  switch (Type) {
  default:
    llvm_unreachable("Relocation type not implemented yet!");
    break;
  case ELF::R_AARCH64_ABS64: {
    uint64_t *TargetPtr = reinterpret_cast<uint64_t*>(Section.Address + Offset);
    *TargetPtr = Value + Addend;
    break;
  }
  case ELF::R_AARCH64_PREL32: {
    uint64_t Result = Value + Addend - FinalAddress;
    assert(static_cast<int64_t>(Result) >= INT32_MIN &&
           static_cast<int64_t>(Result) <= UINT32_MAX);
    *TargetPtr = static_cast<uint32_t>(Result & 0xffffffffU);
    break;
  }
  case ELF::R_AARCH64_CALL26: // fallthrough
  case ELF::R_AARCH64_JUMP26: {
    // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the
    // calculation.
    uint64_t BranchImm = Value + Addend - FinalAddress;

    // "Check that -2^27 <= result < 2^27".
    assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) &&
           static_cast<int64_t>(BranchImm) < (1LL << 27));

    // AArch64 code is emitted with .rela relocations. The data already in any
    // bits affected by the relocation on entry is garbage.
    *TargetPtr &= 0xfc000000U;
    // Immediate goes in bits 25:0 of B and BL.
    *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) >> 2;
    break;
  }
  case ELF::R_AARCH64_MOVW_UABS_G3: {
    uint64_t Result = Value + Addend;

    // AArch64 code is emitted with .rela relocations. The data already in any
    // bits affected by the relocation on entry is garbage.
    *TargetPtr &= 0xffe0001fU;
    // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
    *TargetPtr |= Result >> (48 - 5);
    // Shift must be "lsl #48", in bits 22:21
    assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation");
    break;
  }
  case ELF::R_AARCH64_MOVW_UABS_G2_NC: {
    uint64_t Result = Value + Addend;

    // AArch64 code is emitted with .rela relocations. The data already in any
    // bits affected by the relocation on entry is garbage.
    *TargetPtr &= 0xffe0001fU;
    // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
    *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5));
    // Shift must be "lsl #32", in bits 22:21
    assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation");
    break;
  }
  case ELF::R_AARCH64_MOVW_UABS_G1_NC: {
    uint64_t Result = Value + Addend;

    // AArch64 code is emitted with .rela relocations. The data already in any
    // bits affected by the relocation on entry is garbage.
    *TargetPtr &= 0xffe0001fU;
    // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
    *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5));
    // Shift must be "lsl #16", in bits 22:2
    assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation");
    break;
  }
  case ELF::R_AARCH64_MOVW_UABS_G0_NC: {
    uint64_t Result = Value + Addend;

    // AArch64 code is emitted with .rela relocations. The data already in any
    // bits affected by the relocation on entry is garbage.
    *TargetPtr &= 0xffe0001fU;
    // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
    *TargetPtr |= ((Result & 0xffffU) << 5);
    // Shift must be "lsl #0", in bits 22:21.
    assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation");
    break;
  }
  }
}

void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
                                          uint64_t Offset,
                                          uint32_t Value,
                                          uint32_t Type,
                                          int32_t Addend) {
  // TODO: Add Thumb relocations.
  uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
                                                      Offset);
  uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
  uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
  Value += Addend;

  DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: "
               << Section.Address + Offset
               << " FinalAddress: " << format("%p",FinalAddress)
               << " Value: " << format("%x",Value)
               << " Type: " << format("%x",Type)
               << " Addend: " << format("%x",Addend)
               << "\n");

  switch(Type) {
  default:
    llvm_unreachable("Not implemented relocation type!");

  // Write a 32bit value to relocation address, taking into account the
  // implicit addend encoded in the target.
  case ELF::R_ARM_TARGET1:
  case ELF::R_ARM_ABS32:
    *TargetPtr = *Placeholder + Value;
    break;
  // Write first 16 bit of 32 bit value to the mov instruction.
  // Last 4 bit should be shifted.
  case ELF::R_ARM_MOVW_ABS_NC:
    // We are not expecting any other addend in the relocation address.
    // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
    // non-contiguous fields.
    assert((*Placeholder & 0x000F0FFF) == 0);
    Value = Value & 0xFFFF;
    *TargetPtr = *Placeholder | (Value & 0xFFF);
    *TargetPtr |= ((Value >> 12) & 0xF) << 16;
    break;
  // Write last 16 bit of 32 bit value to the mov instruction.
  // Last 4 bit should be shifted.
  case ELF::R_ARM_MOVT_ABS:
    // We are not expecting any other addend in the relocation address.
    // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC.
    assert((*Placeholder & 0x000F0FFF) == 0);

    Value = (Value >> 16) & 0xFFFF;
    *TargetPtr = *Placeholder | (Value & 0xFFF);
    *TargetPtr |= ((Value >> 12) & 0xF) << 16;
    break;
  // Write 24 bit relative value to the branch instruction.
  case ELF::R_ARM_PC24 :    // Fall through.
  case ELF::R_ARM_CALL :    // Fall through.
  case ELF::R_ARM_JUMP24: {
    int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
    RelValue = (RelValue & 0x03FFFFFC) >> 2;
    assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE);
    *TargetPtr &= 0xFF000000;
    *TargetPtr |= RelValue;
    break;
  }
  case ELF::R_ARM_PRIVATE_0:
    // This relocation is reserved by the ARM ELF ABI for internal use. We
    // appropriate it here to act as an R_ARM_ABS32 without any addend for use
    // in the stubs created during JIT (which can't put an addend into the
    // original object file).
    *TargetPtr = Value;
    break;
  }
}

void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
                                           uint64_t Offset,
                                           uint32_t Value,
                                           uint32_t Type,
                                           int32_t Addend) {
  uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
                                                      Offset);
  uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
  Value += Addend;

  DEBUG(dbgs() << "resolveMipselocation, LocalAddress: "
               << Section.Address + Offset
               << " FinalAddress: "
               << format("%p",Section.LoadAddress + Offset)
               << " Value: " << format("%x",Value)
               << " Type: " << format("%x",Type)
               << " Addend: " << format("%x",Addend)
               << "\n");

  switch(Type) {
  default:
    llvm_unreachable("Not implemented relocation type!");
    break;
  case ELF::R_MIPS_32:
    *TargetPtr = Value + (*Placeholder);
    break;
  case ELF::R_MIPS_26:
    *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2);
    break;
  case ELF::R_MIPS_HI16:
    // Get the higher 16-bits. Also add 1 if bit 15 is 1.
    Value += ((*Placeholder) & 0x0000ffff) << 16;
    *TargetPtr = ((*Placeholder) & 0xffff0000) |
                 (((Value + 0x8000) >> 16) & 0xffff);
    break;
  case ELF::R_MIPS_LO16:
    Value += ((*Placeholder) & 0x0000ffff);
    *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff);
    break;
  case ELF::R_MIPS_UNUSED1:
    // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2
    // are used for internal JIT purpose. These relocations are similar to
    // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into
    // account.
    *TargetPtr = ((*TargetPtr) & 0xffff0000) |
                 (((Value + 0x8000) >> 16) & 0xffff);
    break;
  case ELF::R_MIPS_UNUSED2:
    *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff);
    break;
   }
}

// Return the .TOC. section address to R_PPC64_TOC relocations.
uint64_t RuntimeDyldELF::findPPC64TOC() const {
  // The TOC consists of sections .got, .toc, .tocbss, .plt in that
  // order. The TOC starts where the first of these sections starts.
  SectionList::const_iterator it = Sections.begin();
  SectionList::const_iterator ite = Sections.end();
  for (; it != ite; ++it) {
    if (it->Name == ".got" ||
        it->Name == ".toc" ||
        it->Name == ".tocbss" ||
        it->Name == ".plt")
      break;
  }
  if (it == ite) {
    // This may happen for
    // * references to TOC base base (sym@toc, .odp relocation) without
    // a .toc directive.
    // In this case just use the first section (which is usually
    // the .odp) since the code won't reference the .toc base
    // directly.
    it = Sections.begin();
  }
  assert (it != ite);
  // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
  // thus permitting a full 64 Kbytes segment.
  return it->LoadAddress + 0x8000;
}

// Returns the sections and offset associated with the ODP entry referenced
// by Symbol.
void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
                                         ObjSectionToIDMap &LocalSections,
                                         RelocationValueRef &Rel) {
  // Get the ELF symbol value (st_value) to compare with Relocation offset in
  // .opd entries

  error_code err;
  for (section_iterator si = Obj.begin_sections(),
     se = Obj.end_sections(); si != se; si.increment(err)) {
    section_iterator RelSecI = si->getRelocatedSection();
    if (RelSecI == Obj.end_sections())
      continue;

    StringRef RelSectionName;
    check(RelSecI->getName(RelSectionName));
    if (RelSectionName != ".opd")
      continue;

    for (relocation_iterator i = si->begin_relocations(),
         e = si->end_relocations(); i != e;) {
      check(err);

      // The R_PPC64_ADDR64 relocation indicates the first field
      // of a .opd entry
      uint64_t TypeFunc;
      check(i->getType(TypeFunc));
      if (TypeFunc != ELF::R_PPC64_ADDR64) {
        i.increment(err);
        continue;
      }

      uint64_t TargetSymbolOffset;
      symbol_iterator TargetSymbol = i->getSymbol();
      check(i->getOffset(TargetSymbolOffset));
      int64_t Addend;
      check(getELFRelocationAddend(*i, Addend));

      i = i.increment(err);
      if (i == e)
        break;
      check(err);

      // Just check if following relocation is a R_PPC64_TOC
      uint64_t TypeTOC;
      check(i->getType(TypeTOC));
      if (TypeTOC != ELF::R_PPC64_TOC)
        continue;

      // Finally compares the Symbol value and the target symbol offset
      // to check if this .opd entry refers to the symbol the relocation
      // points to.
      if (Rel.Addend != (int64_t)TargetSymbolOffset)
        continue;

      section_iterator tsi(Obj.end_sections());
      check(TargetSymbol->getSection(tsi));
      Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections);
      Rel.Addend = (intptr_t)Addend;
      return;
    }
  }
  llvm_unreachable("Attempting to get address of ODP entry!");
}

// Relocation masks following the #lo(value), #hi(value), #higher(value),
// and #highest(value) macros defined in section 4.5.1. Relocation Types
// in PPC-elf64abi document.
//
static inline
uint16_t applyPPClo (uint64_t value)
{
  return value & 0xffff;
}

static inline
uint16_t applyPPChi (uint64_t value)
{
  return (value >> 16) & 0xffff;
}

static inline
uint16_t applyPPChigher (uint64_t value)
{
  return (value >> 32) & 0xffff;
}

static inline
uint16_t applyPPChighest (uint64_t value)
{
  return (value >> 48) & 0xffff;
}

void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
                                            uint64_t Offset,
                                            uint64_t Value,
                                            uint32_t Type,
                                            int64_t Addend) {
  uint8_t* LocalAddress = Section.Address + Offset;
  switch (Type) {
  default:
    llvm_unreachable("Relocation type not implemented yet!");
  break;
  case ELF::R_PPC64_ADDR16_LO :
    writeInt16BE(LocalAddress, applyPPClo (Value + Addend));
    break;
  case ELF::R_PPC64_ADDR16_HI :
    writeInt16BE(LocalAddress, applyPPChi (Value + Addend));
    break;
  case ELF::R_PPC64_ADDR16_HIGHER :
    writeInt16BE(LocalAddress, applyPPChigher (Value + Addend));
    break;
  case ELF::R_PPC64_ADDR16_HIGHEST :
    writeInt16BE(LocalAddress, applyPPChighest (Value + Addend));
    break;
  case ELF::R_PPC64_ADDR14 : {
    assert(((Value + Addend) & 3) == 0);
    // Preserve the AA/LK bits in the branch instruction
    uint8_t aalk = *(LocalAddress+3);
    writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));
  } break;
  case ELF::R_PPC64_ADDR32 : {
    int32_t Result = static_cast<int32_t>(Value + Addend);
    if (SignExtend32<32>(Result) != Result)
      llvm_unreachable("Relocation R_PPC64_ADDR32 overflow");
    writeInt32BE(LocalAddress, Result);
  } break;
  case ELF::R_PPC64_REL24 : {
    uint64_t FinalAddress = (Section.LoadAddress + Offset);
    int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
    if (SignExtend32<24>(delta) != delta)
      llvm_unreachable("Relocation R_PPC64_REL24 overflow");
    // Generates a 'bl <address>' instruction
    writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC));
  } break;
  case ELF::R_PPC64_REL32 : {
    uint64_t FinalAddress = (Section.LoadAddress + Offset);
    int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
    if (SignExtend32<32>(delta) != delta)
      llvm_unreachable("Relocation R_PPC64_REL32 overflow");
    writeInt32BE(LocalAddress, delta);
  } break;
  case ELF::R_PPC64_REL64: {
    uint64_t FinalAddress = (Section.LoadAddress + Offset);
    uint64_t Delta = Value - FinalAddress + Addend;
    writeInt64BE(LocalAddress, Delta);
  } break;
  case ELF::R_PPC64_ADDR64 :
    writeInt64BE(LocalAddress, Value + Addend);
    break;
  case ELF::R_PPC64_TOC :
    writeInt64BE(LocalAddress, findPPC64TOC());
    break;
  case ELF::R_PPC64_TOC16 : {
    uint64_t TOCStart = findPPC64TOC();
    Value = applyPPClo((Value + Addend) - TOCStart);
    writeInt16BE(LocalAddress, applyPPClo(Value));
  } break;
  case ELF::R_PPC64_TOC16_DS : {
    uint64_t TOCStart = findPPC64TOC();
    Value = ((Value + Addend) - TOCStart);
    writeInt16BE(LocalAddress, applyPPClo(Value));
  } break;
  }
}

void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
                                              uint64_t Offset,
                                              uint64_t Value,
                                              uint32_t Type,
                                              int64_t Addend) {
  uint8_t *LocalAddress = Section.Address + Offset;
  switch (Type) {
  default:
    llvm_unreachable("Relocation type not implemented yet!");
    break;
  case ELF::R_390_PC16DBL:
  case ELF::R_390_PLT16DBL: {
    int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
    assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow");
    writeInt16BE(LocalAddress, Delta / 2);
    break;
  }
  case ELF::R_390_PC32DBL:
  case ELF::R_390_PLT32DBL: {
    int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
    assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow");
    writeInt32BE(LocalAddress, Delta / 2);
    break;
  }
  case ELF::R_390_PC32: {
    int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
    assert(int32_t(Delta) == Delta && "R_390_PC32 overflow");
    writeInt32BE(LocalAddress, Delta);
    break;
  }
  case ELF::R_390_64:
    writeInt64BE(LocalAddress, Value + Addend);
    break;
  }
}

// The target location for the relocation is described by RE.SectionID and
// RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
// SectionEntry has three members describing its location.
// SectionEntry::Address is the address at which the section has been loaded
// into memory in the current (host) process.  SectionEntry::LoadAddress is the
// address that the section will have in the target process.
// SectionEntry::ObjAddress is the address of the bits for this section in the
// original emitted object image (also in the current address space).
//
// Relocations will be applied as if the section were loaded at
// SectionEntry::LoadAddress, but they will be applied at an address based
// on SectionEntry::Address.  SectionEntry::ObjAddress will be used to refer to
// Target memory contents if they are required for value calculations.
//
// The Value parameter here is the load address of the symbol for the
// relocation to be applied.  For relocations which refer to symbols in the
// current object Value will be the LoadAddress of the section in which
// the symbol resides (RE.Addend provides additional information about the
// symbol location).  For external symbols, Value will be the address of the
// symbol in the target address space.
void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
                                       uint64_t Value) {
  const SectionEntry &Section = Sections[RE.SectionID];
  return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
                           RE.SymOffset);
}

void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
                                       uint64_t Offset,
                                       uint64_t Value,
                                       uint32_t Type,
                                       int64_t  Addend,
                                       uint64_t SymOffset) {
  switch (Arch) {
  case Triple::x86_64:
    resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset);
    break;
  case Triple::x86:
    resolveX86Relocation(Section, Offset,
                         (uint32_t)(Value & 0xffffffffL), Type,
                         (uint32_t)(Addend & 0xffffffffL));
    break;
  case Triple::aarch64:
    resolveAArch64Relocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::arm:    // Fall through.
  case Triple::thumb:
    resolveARMRelocation(Section, Offset,
                         (uint32_t)(Value & 0xffffffffL), Type,
                         (uint32_t)(Addend & 0xffffffffL));
    break;
  case Triple::mips:    // Fall through.
  case Triple::mipsel:
    resolveMIPSRelocation(Section, Offset,
                          (uint32_t)(Value & 0xffffffffL), Type,
                          (uint32_t)(Addend & 0xffffffffL));
    break;
  case Triple::ppc64:   // Fall through.
  case Triple::ppc64le:
    resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::systemz:
    resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
    break;
  default: llvm_unreachable("Unsupported CPU type!");
  }
}

void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
                                          RelocationRef RelI,
                                          ObjectImage &Obj,
                                          ObjSectionToIDMap &ObjSectionToID,
                                          const SymbolTableMap &Symbols,
                                          StubMap &Stubs) {
  uint64_t RelType;
  Check(RelI.getType(RelType));
  int64_t Addend;
  Check(getELFRelocationAddend(RelI, Addend));
  symbol_iterator Symbol = RelI.getSymbol();

  // Obtain the symbol name which is referenced in the relocation
  StringRef TargetName;
  if (Symbol != Obj.end_symbols())
    Symbol->getName(TargetName);
  DEBUG(dbgs() << "\t\tRelType: " << RelType
               << " Addend: " << Addend
               << " TargetName: " << TargetName
               << "\n");
  RelocationValueRef Value;
  // First search for the symbol in the local symbol table
  SymbolTableMap::const_iterator lsi = Symbols.end();
  SymbolRef::Type SymType = SymbolRef::ST_Unknown;
  if (Symbol != Obj.end_symbols()) {
    lsi = Symbols.find(TargetName.data());
    Symbol->getType(SymType);
  }
  if (lsi != Symbols.end()) {
    Value.SectionID = lsi->second.first;
    Value.Offset = lsi->second.second;
    Value.Addend = lsi->second.second + Addend;
  } else {
    // Search for the symbol in the global symbol table
    SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
    if (Symbol != Obj.end_symbols())
      gsi = GlobalSymbolTable.find(TargetName.data());
    if (gsi != GlobalSymbolTable.end()) {
      Value.SectionID = gsi->second.first;
      Value.Offset = gsi->second.second;
      Value.Addend = gsi->second.second + Addend;
    } else {
      switch (SymType) {
        case SymbolRef::ST_Debug: {
          // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
          // and can be changed by another developers. Maybe best way is add
          // a new symbol type ST_Section to SymbolRef and use it.
          section_iterator si(Obj.end_sections());
          Symbol->getSection(si);
          if (si == Obj.end_sections())
            llvm_unreachable("Symbol section not found, bad object file format!");
          DEBUG(dbgs() << "\t\tThis is section symbol\n");
          // Default to 'true' in case isText fails (though it never does).
          bool isCode = true;
          si->isText(isCode);
          Value.SectionID = findOrEmitSection(Obj,
                                              (*si),
                                              isCode,
                                              ObjSectionToID);
          Value.Addend = Addend;
          break;
        }
        case SymbolRef::ST_Data:
        case SymbolRef::ST_Unknown: {
          Value.SymbolName = TargetName.data();
          Value.Addend = Addend;

          // Absolute relocations will have a zero symbol ID (STN_UNDEF), which
          // will manifest here as a NULL symbol name.
          // We can set this as a valid (but empty) symbol name, and rely
          // on addRelocationForSymbol to handle this.
          if (!Value.SymbolName)
              Value.SymbolName = "";
          break;
        }
        default:
          llvm_unreachable("Unresolved symbol type!");
          break;
      }
    }
  }
  uint64_t Offset;
  Check(RelI.getOffset(Offset));

  DEBUG(dbgs() << "\t\tSectionID: " << SectionID
               << " Offset: " << Offset
               << "\n");
  if (Arch == Triple::aarch64 &&
      (RelType == ELF::R_AARCH64_CALL26 ||
       RelType == ELF::R_AARCH64_JUMP26)) {
    // This is an AArch64 branch relocation, need to use a stub function.
    DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");
    SectionEntry &Section = Sections[SectionID];

    // Look for an existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end()) {
        resolveRelocation(Section, Offset,
                          (uint64_t)Section.Address + i->second, RelType, 0);
      DEBUG(dbgs() << " Stub function found\n");
    } else {
      // Create a new stub function.
      DEBUG(dbgs() << " Create a new stub function\n");
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);

      RelocationEntry REmovz_g3(SectionID,
                                StubTargetAddr - Section.Address,
                                ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);
      RelocationEntry REmovk_g2(SectionID,
                                StubTargetAddr - Section.Address + 4,
                                ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);
      RelocationEntry REmovk_g1(SectionID,
                                StubTargetAddr - Section.Address + 8,
                                ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);
      RelocationEntry REmovk_g0(SectionID,
                                StubTargetAddr - Section.Address + 12,
                                ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);

      if (Value.SymbolName) {
        addRelocationForSymbol(REmovz_g3, Value.SymbolName);
        addRelocationForSymbol(REmovk_g2, Value.SymbolName);
        addRelocationForSymbol(REmovk_g1, Value.SymbolName);
        addRelocationForSymbol(REmovk_g0, Value.SymbolName);
      } else {
        addRelocationForSection(REmovz_g3, Value.SectionID);
        addRelocationForSection(REmovk_g2, Value.SectionID);
        addRelocationForSection(REmovk_g1, Value.SectionID);
        addRelocationForSection(REmovk_g0, Value.SectionID);
      }
      resolveRelocation(Section, Offset,
                        (uint64_t)Section.Address + Section.StubOffset,
                        RelType, 0);
      Section.StubOffset += getMaxStubSize();
    }
  } else if (Arch == Triple::arm &&
      (RelType == ELF::R_ARM_PC24 ||
       RelType == ELF::R_ARM_CALL ||
       RelType == ELF::R_ARM_JUMP24)) {
    // This is an ARM branch relocation, need to use a stub function.
    DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
    SectionEntry &Section = Sections[SectionID];

    // Look for an existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end()) {
        resolveRelocation(Section, Offset,
                          (uint64_t)Section.Address + i->second, RelType, 0);
      DEBUG(dbgs() << " Stub function found\n");
    } else {
      // Create a new stub function.
      DEBUG(dbgs() << " Create a new stub function\n");
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);
      RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
                         ELF::R_ARM_PRIVATE_0, Value.Addend);
      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);

      resolveRelocation(Section, Offset,
                        (uint64_t)Section.Address + Section.StubOffset,
                        RelType, 0);
      Section.StubOffset += getMaxStubSize();
    }
  } else if ((Arch == Triple::mipsel || Arch == Triple::mips) &&
             RelType == ELF::R_MIPS_26) {
    // This is an Mips branch relocation, need to use a stub function.
    DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");
    SectionEntry &Section = Sections[SectionID];
    uint8_t *Target = Section.Address + Offset;
    uint32_t *TargetAddress = (uint32_t *)Target;

    // Extract the addend from the instruction.
    uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2;

    Value.Addend += Addend;

    //  Look up for existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end()) {
      RelocationEntry RE(SectionID, Offset, RelType, i->second);
      addRelocationForSection(RE, SectionID);
      DEBUG(dbgs() << " Stub function found\n");
    } else {
      // Create a new stub function.
      DEBUG(dbgs() << " Create a new stub function\n");
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);

      // Creating Hi and Lo relocations for the filled stub instructions.
      RelocationEntry REHi(SectionID,
                           StubTargetAddr - Section.Address,
                           ELF::R_MIPS_UNUSED1, Value.Addend);
      RelocationEntry RELo(SectionID,
                           StubTargetAddr - Section.Address + 4,
                           ELF::R_MIPS_UNUSED2, Value.Addend);

      if (Value.SymbolName) {
        addRelocationForSymbol(REHi, Value.SymbolName);
        addRelocationForSymbol(RELo, Value.SymbolName);
      } else {
        addRelocationForSection(REHi, Value.SectionID);
        addRelocationForSection(RELo, Value.SectionID);
      }

      RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset);
      addRelocationForSection(RE, SectionID);
      Section.StubOffset += getMaxStubSize();
    }
  } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
    if (RelType == ELF::R_PPC64_REL24) {
      // A PPC branch relocation will need a stub function if the target is
      // an external symbol (Symbol::ST_Unknown) or if the target address
      // is not within the signed 24-bits branch address.
      SectionEntry &Section = Sections[SectionID];
      uint8_t *Target = Section.Address + Offset;
      bool RangeOverflow = false;
      if (SymType != SymbolRef::ST_Unknown) {
        // A function call may points to the .opd entry, so the final symbol value
        // in calculated based in the relocation values in .opd section.
        findOPDEntrySection(Obj, ObjSectionToID, Value);
        uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend;
        int32_t delta = static_cast<int32_t>(Target - RelocTarget);
        // If it is within 24-bits branch range, just set the branch target
        if (SignExtend32<24>(delta) == delta) {
          RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
          if (Value.SymbolName)
            addRelocationForSymbol(RE, Value.SymbolName);
          else
            addRelocationForSection(RE, Value.SectionID);
        } else {
          RangeOverflow = true;
        }
      }
      if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) {
        // It is an external symbol (SymbolRef::ST_Unknown) or within a range
        // larger than 24-bits.
        StubMap::const_iterator i = Stubs.find(Value);
        if (i != Stubs.end()) {
          // Symbol function stub already created, just relocate to it
          resolveRelocation(Section, Offset,
                            (uint64_t)Section.Address + i->second, RelType, 0);
          DEBUG(dbgs() << " Stub function found\n");
        } else {
          // Create a new stub function.
          DEBUG(dbgs() << " Create a new stub function\n");
          Stubs[Value] = Section.StubOffset;
          uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                       Section.StubOffset);
          RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
                             ELF::R_PPC64_ADDR64, Value.Addend);

          // Generates the 64-bits address loads as exemplified in section
          // 4.5.1 in PPC64 ELF ABI.
          RelocationEntry REhst(SectionID,
                                StubTargetAddr - Section.Address + 2,
                                ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend);
          RelocationEntry REhr(SectionID,
                               StubTargetAddr - Section.Address + 6,
                               ELF::R_PPC64_ADDR16_HIGHER, Value.Addend);
          RelocationEntry REh(SectionID,
                              StubTargetAddr - Section.Address + 14,
                              ELF::R_PPC64_ADDR16_HI, Value.Addend);
          RelocationEntry REl(SectionID,
                              StubTargetAddr - Section.Address + 18,
                              ELF::R_PPC64_ADDR16_LO, Value.Addend);

          if (Value.SymbolName) {
            addRelocationForSymbol(REhst, Value.SymbolName);
            addRelocationForSymbol(REhr,  Value.SymbolName);
            addRelocationForSymbol(REh,   Value.SymbolName);
            addRelocationForSymbol(REl,   Value.SymbolName);
          } else {
            addRelocationForSection(REhst, Value.SectionID);
            addRelocationForSection(REhr,  Value.SectionID);
            addRelocationForSection(REh,   Value.SectionID);
            addRelocationForSection(REl,   Value.SectionID);
          }

          resolveRelocation(Section, Offset,
                            (uint64_t)Section.Address + Section.StubOffset,
                            RelType, 0);
          if (SymType == SymbolRef::ST_Unknown)
            // Restore the TOC for external calls
            writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
          Section.StubOffset += getMaxStubSize();
        }
      }
    } else {
      RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
      // Extra check to avoid relocation againt empty symbols (usually
      // the R_PPC64_TOC).
      if (SymType != SymbolRef::ST_Unknown && TargetName.empty())
        Value.SymbolName = NULL;

      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);
    }
  } else if (Arch == Triple::systemz &&
             (RelType == ELF::R_390_PLT32DBL ||
              RelType == ELF::R_390_GOTENT)) {
    // Create function stubs for both PLT and GOT references, regardless of
    // whether the GOT reference is to data or code.  The stub contains the
    // full address of the symbol, as needed by GOT references, and the
    // executable part only adds an overhead of 8 bytes.
    //
    // We could try to conserve space by allocating the code and data
    // parts of the stub separately.  However, as things stand, we allocate
    // a stub for every relocation, so using a GOT in JIT code should be
    // no less space efficient than using an explicit constant pool.
    DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation.");
    SectionEntry &Section = Sections[SectionID];

    // Look for an existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    uintptr_t StubAddress;
    if (i != Stubs.end()) {
      StubAddress = uintptr_t(Section.Address) + i->second;
      DEBUG(dbgs() << " Stub function found\n");
    } else {
      // Create a new stub function.
      DEBUG(dbgs() << " Create a new stub function\n");

      uintptr_t BaseAddress = uintptr_t(Section.Address);
      uintptr_t StubAlignment = getStubAlignment();
      StubAddress = (BaseAddress + Section.StubOffset +
                     StubAlignment - 1) & -StubAlignment;
      unsigned StubOffset = StubAddress - BaseAddress;

      Stubs[Value] = StubOffset;
      createStubFunction((uint8_t *)StubAddress);
      RelocationEntry RE(SectionID, StubOffset + 8,
                         ELF::R_390_64, Value.Addend - Addend);
      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);
      Section.StubOffset = StubOffset + getMaxStubSize();
    }

    if (RelType == ELF::R_390_GOTENT)
      resolveRelocation(Section, Offset, StubAddress + 8,
                        ELF::R_390_PC32DBL, Addend);
    else
      resolveRelocation(Section, Offset, StubAddress, RelType, Addend);
  } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_PLT32) {
    // The way the PLT relocations normally work is that the linker allocates the
    // PLT and this relocation makes a PC-relative call into the PLT.  The PLT
    // entry will then jump to an address provided by the GOT.  On first call, the
    // GOT address will point back into PLT code that resolves the symbol.  After
    // the first call, the GOT entry points to the actual function.
    //
    // For local functions we're ignoring all of that here and just replacing
    // the PLT32 relocation type with PC32, which will translate the relocation
    // into a PC-relative call directly to the function. For external symbols we
    // can't be sure the function will be within 2^32 bytes of the call site, so
    // we need to create a stub, which calls into the GOT.  This case is
    // equivalent to the usual PLT implementation except that we use the stub
    // mechanism in RuntimeDyld (which puts stubs at the end of the section)
    // rather than allocating a PLT section.
    if (Value.SymbolName) {
      // This is a call to an external function.
      // Look for an existing stub.
      SectionEntry &Section = Sections[SectionID];
      StubMap::const_iterator i = Stubs.find(Value);
      uintptr_t StubAddress;
      if (i != Stubs.end()) {
        StubAddress = uintptr_t(Section.Address) + i->second;
        DEBUG(dbgs() << " Stub function found\n");
      } else {
        // Create a new stub function (equivalent to a PLT entry).
        DEBUG(dbgs() << " Create a new stub function\n");

        uintptr_t BaseAddress = uintptr_t(Section.Address);
        uintptr_t StubAlignment = getStubAlignment();
        StubAddress = (BaseAddress + Section.StubOffset +
                      StubAlignment - 1) & -StubAlignment;
        unsigned StubOffset = StubAddress - BaseAddress;
        Stubs[Value] = StubOffset;
        createStubFunction((uint8_t *)StubAddress);

        // Create a GOT entry for the external function.
        GOTEntries.push_back(Value);

        // Make our stub function a relative call to the GOT entry.
        RelocationEntry RE(SectionID, StubOffset + 2,
                           ELF::R_X86_64_GOTPCREL, -4);
        addRelocationForSymbol(RE, Value.SymbolName);

        // Bump our stub offset counter
        Section.StubOffset = StubOffset + getMaxStubSize();
      }

      // Make the target call a call into the stub table.
      resolveRelocation(Section, Offset, StubAddress,
                      ELF::R_X86_64_PC32, Addend);
    } else {
      RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend,
                         Value.Offset);
      addRelocationForSection(RE, Value.SectionID);
    }
  } else {
    if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) {
      GOTEntries.push_back(Value);
    }
    RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset);
    if (Value.SymbolName)
      addRelocationForSymbol(RE, Value.SymbolName);
    else
      addRelocationForSection(RE, Value.SectionID);
  }
}

void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) {

  SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator it;
  SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator end = GOTs.end();

  for (it = GOTs.begin(); it != end; ++it) {
    GOTRelocations &GOTEntries = it->second;
    for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
      if (GOTEntries[i].SymbolName != 0 && GOTEntries[i].SymbolName == Name) {
        GOTEntries[i].Offset = Addr;
      }
    }
  }
}

size_t RuntimeDyldELF::getGOTEntrySize() {
  // We don't use the GOT in all of these cases, but it's essentially free
  // to put them all here.
  size_t Result = 0;
  switch (Arch) {
  case Triple::x86_64:
  case Triple::aarch64:
  case Triple::ppc64:
  case Triple::ppc64le:
  case Triple::systemz:
    Result = sizeof(uint64_t);
    break;
  case Triple::x86:
  case Triple::arm:
  case Triple::thumb:
  case Triple::mips:
  case Triple::mipsel:
    Result = sizeof(uint32_t);
    break;
  default: llvm_unreachable("Unsupported CPU type!");
  }
  return Result;
}

uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress,
                                      uint64_t Offset) {

  const size_t GOTEntrySize = getGOTEntrySize();

  SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator it;
  SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator end = GOTs.end();

  int GOTIndex = -1;
  for (it = GOTs.begin(); it != end; ++it) {
    SID GOTSectionID = it->first;
    const GOTRelocations &GOTEntries = it->second;

    // Find the matching entry in our vector.
    uint64_t SymbolOffset = 0;
    for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
      if (GOTEntries[i].SymbolName == 0) {
        if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress &&
            GOTEntries[i].Offset == Offset) {
          GOTIndex = i;
          SymbolOffset = GOTEntries[i].Offset;
          break;
        }
      } else {
        // GOT entries for external symbols use the addend as the address when
        // the external symbol has been resolved.
        if (GOTEntries[i].Offset == LoadAddress) {
          GOTIndex = i;
          // Don't use the Addend here.  The relocation handler will use it.
          break;
        }
      }
    }

    if (GOTIndex != -1) {
      if (GOTEntrySize == sizeof(uint64_t)) {
        uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID);
        // Fill in this entry with the address of the symbol being referenced.
        LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset;
      } else {
        uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID);
        // Fill in this entry with the address of the symbol being referenced.
        LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset);
      }

      // Calculate the load address of this entry
      return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize);
    }
  }

  assert(GOTIndex != -1 && "Unable to find requested GOT entry.");
  return 0;
}

void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) {
  // If necessary, allocate the global offset table
  if (MemMgr) {
    // Allocate the GOT if necessary
    size_t numGOTEntries = GOTEntries.size();
    if (numGOTEntries != 0) {
      // Allocate memory for the section
      unsigned SectionID = Sections.size();
      size_t TotalSize = numGOTEntries * getGOTEntrySize();
      uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(),
                                                  SectionID, ".got", false);
      if (!Addr)
        report_fatal_error("Unable to allocate memory for GOT!");

      GOTs.push_back(std::make_pair(SectionID, GOTEntries));
      Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0));
      // For now, initialize all GOT entries to zero.  We'll fill them in as
      // needed when GOT-based relocations are applied.
      memset(Addr, 0, TotalSize);
    }
  }
  else {
    report_fatal_error("Unable to allocate memory for GOT!");
  }

  // Look for and record the EH frame section.
  ObjSectionToIDMap::iterator i, e;
  for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
    const SectionRef &Section = i->first;
    StringRef Name;
    Section.getName(Name);
    if (Name == ".eh_frame") {
      UnregisteredEHFrameSections.push_back(i->second);
      break;
    }
  }
}

bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
  if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
    return false;
  return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
}
} // namespace llvm


text:
Home Music Watch: EXO wins Album of the Year at 2016 MAMA Awards
Watch: EXO wins Album of the Year at 2016 MAMA Awards
EXO is the announced Album of the Year winner at the 2016 MAMA MNET Asian Music Awards on Friday, December 2, 2016.
EXO wins the 2016 MAMA Album of the Year award on Friday — the group took the biggest award in Kpop Music for the 4th time this year.
Watch on the vide below.
BTS WON ARTIST OF THE YEAR! #BTS #방탄소년단 #MAMA2016 pic.twitter.com/Ze1nNf1ErN
— US BTS ARMY (@USBTSARMY) December 2, 2016
Meanwhile, BTS wins the Artist of the Year award while TWICE clinches the Song of the Year award for Cheer Up.
ZICO and Taeyeon also win the best male and female artists award this year. See full list of winners here!
What can you say about the results of the 2016 MAMA Awards? Share your comments and views on the discussion box below.
Previous article2016 MAMA MNET Asian Music Awards Winners and Results
Next articleK-Pop 2016 MAMA MNET Asian Music Awards Live Coverage, Performances, Replay and Highlights Video
Tyler Butler-Figueroa Golden Buzzer America's Got Talent 2019 Audition Performance Video
Top 10 Songs Billboard Hot 100 Chart 08/04/18 – Drake "In my Feelings" at #1
K-Pop 2016 MAMA MNET Asian Music Awards Live Coverage, Performances, Replay and Highlights Video

redpajama_set_name: RedPajamaCommonCrawl


Author Gary Thomas outlines some important, biblically-based character attributes which singles should look for in a future spouse.... Having a real relationship with God (as opposed to a relationship with your church, and do not think that this exists only with the high liturgical ones, it is also found in the fundamental evangelical ones), is something that is hard to find in older people, much less young ones.
20/01/2018 · Independent, Fundamental, KJV Bible Only, Soulwinning Baptist Preaching. Word of Truth Baptist Church in Prescott Valley, AZ. Pastor David Berzins.
25/07/2018 · The truth therefore is that godly spouses exist, though maybe a little bit hard to find but adopting the following rules will help you: THINGS YOU SHOULD NOT DO IN FINDING A GODLY SPOUSE 1.
Featured Curriculum Ready To Wed ™ Kit. Features an engaging 10-session DVD series, a leader's guide, two copies of the couple's workbook and the humorous and insightful book co-authored by Dr. Greg and Erin Smalley, Ready to Wed.
The main thing concerns God's will for your life and your potential spouse. After all is said and done, just where does the will of God enter into all of this discussion?


Broadway will be getting a little more 90s soon with word that the cult classic Empire Records is going to be turned into a musical.
I am certainly psyched about this one and really hope they get to use some of the actual 90s hits from the film in the stage version.
Of course there will be plenty of new songs as well as Empire Records is brought to life on the Great White Way.
Rolling Stone reports that the original screenwriter Carol Heikkinen is joining forces with composer Zoe Sarnak to make this musical happen.
The Broadway version will follow the same basic plot as the movie, following the young store employees as the celebrate Rex Manning Day on Sunday April 8th.
Heikkinen tells Rolling Stone that she's not sure every scene from the film will make it into the Broadway version, but she does believe the new format will allow her to develop her characters a bit more.
The storyline of a record store going out of business and the state of the music industry is definitely one that is still very relevant today.
Unfortunately we will all still have to wait a bit to actually see the stage version of this classic film.
Empire Records isn't expected to hit Broadway until 2020.


text:
Petit Le Mans at Road America
mbenken's blog
Edwards Scores Continental Win at Kansas
Kansas, KS. (Aug. 19). Saturday at Kansas Speedway with Stevenson Motorsports co-driver Matt Bell, John Edwards earned his fifth career victory in the Continental Tire Sports Car Challenge. The win marked the second CTSCC win for Bell and Edwards this season. Edwards and co-driver Robin Liddell also earned their 6th top-five finish of the season in the Rolex Sports Car Series.
Second Place Finish and NAEC Title for Edwards at Indianapolis
Speedway, IN. (Jul. 28). Another round of the Rolex Sports Car Series and the Continental Tire Sports Car Challenge is complete for John Edwards after the Brickyard Grand Prix. In addition to winning the North American Endurance Championship, Edwards and co-driver Robin Liddell earned their fifth Rolex GT podium in eight races with Stevenson Motorsports at the legendary Indianapolis Motor Speedway.
Edwards Earns First ALMS Win with Müller and BMW RLL Racing
Lakeville, CT. (Jul. 8) - In his third American Le Mans Series Start, John Edwards not only claimed the fastest lap time in the GT qualifying session at Lime Rock Park, but also earned his first ALMS win with co-driver Dirk Müller and team BMW RLL Racing. The team showed strength all weekend long, setting the fastest laps in both practice sessions and in Friday's qualifying session.
Edwards and Liddell Win Rolex GT at Watkins Glen
Watkins Glen, NY. (Jun. 30). Sunday at Watkins Glen International, John Edwards, Robin Liddell and the Stevenson Motorsports team earned their fourth win of the Rolex Sports Car Series Season. Liddell qualified the 57 Camaro on pole position for the Rolex Series Sahlen's Six Hours of The Glen, setting high the team's hopes of defending their 2012 win on the 3.4 mile road course.


text:
Home Society FDA Announces Steps Aimed at Facilitating E-Cig Innovation
FDA Announces Steps Aimed at Facilitating E-Cig Innovation
Last week, FDA Commissioner Scott Gottlieb, M.D., and director of the Center for Tobacco Products Mitch Zeller, J.D., released a joint statement indicating that they aim to make it easier for new vaping products to be launched on the market.
Diane Caruana
The piece called Advancing Tobacco Regulation to Protect Children and Families: Updates and New Initiatives from the FDA on the Anniversary of the Tobacco Control Act and FDA's Comprehensive Plan for Nicotine, seems to indicate that the agency's prohibitory stance may be a thing of the past. The FDA has finally announced steps geared towards making it easier for manufacturers to launch new and innovative products on the market.
"This summer marks nine years since the Family Smoking Prevention and Tobacco Control Act (TCA) was signed into law, and one year since we announced the FDA's Comprehensive Plan for Tobacco and Nicotine Regulation. This comprehensive plan places nicotine, and the issue of addiction, at the center of the agency's tobacco regulation efforts. The multi-year roadmap provides a framework for regulating nicotine and tobacco and is designed to reframe the conversation around nicotine and harm reduction." reads the piece.
"The multi-year roadmap provides a framework for regulating nicotine and tobacco and is designed to reframe the conversation around nicotine and harm reduction." Dr. Scott Gottlieb, FDA Commisioner
An article on The Examiner, rightly pointed out that since last year, "there hasn't been any clarity, transparency, or efficiency in the approval process for products," as any efforts surrounding the products have included threatening statements related to e-liquid flavour bans and youth vaping.
A transparent framework for manufacturers
However this may be changing. The first step of the announced plan is the most important, as it brings clarity to vaping companies on how to launch new products or keep existing products on the market. Amongst other things, the FDA said that they "will lay out a transparent, modern, and science-based framework for manufacturing practices and the development of tobacco product applications that meet the legal requirements."
Mitch Zeller
scott gottlieb
Previous articleTariffs on Chinese Imports Are Threatening the U.S. Vaping Industry
Next articleVaping bans continue to spread as politicians ignore harm reduction
https://www.vapingpost.com
In-house journalist covering international vaping news.
Most Popular Society News
Guillaume Bailly - September 14, 2016 2
Foreword We have interviewed a number of imams on the stance on e-cigarettes in the Muslim faith... Everyone is free to choose to believe or not....
France: The Ecig officially recognized in tobacco harm reduction
Nathalie Dunand - April 19, 2016 2
"A non-negligible proportion of e-cigarette users significantly reduced the harmful effects of tobacco combustion" About thirty experts were invited at the French Ministry of Health's building...
Current Society News
Society Diane Caruana - January 11, 2022 0
Yach, an anti-tobacco activist who had played a main role in the enactment of the WHO FCTC in 2005, said he doesn't think the...
Society Diane Caruana - January 6, 2022 0
Cigarette butts are known to make up around 20% per cent of the debris gathered during ocean clean-ups.The world's 1.3 billion smokers "improperly dispose...
Premiered on CAPHRA's (Coalition of Asia Pacific Tobacco Harm Reduction Advocates) Facebook page at https://www.facebook.com/caphraorg, and headlined "The battle between innovation and bully tactics,"...


St. Johns Law Group is St. Augustine Beach's full service law firm, representing clients in real estate, commercial and residential, litigation, construction disputes, land use and development, corporate and business law, probate and estate planning, family law and divorce, bankruptcy and disputes related to property. We serve clients in the St. Augustine, Beach, Ponte Vedra, Nocatee, and St. Johns, Florida areas. Also, we provide real estate closings at title company prices.
Seller: St. Johns Law Group, P.A.
St. Johns Law Group and its team of attorneys and staff are committed to providing dedicated and responsive service in the St. Augustine, Beach, Ponte Vedra, Nocatee and St. Johns, Florida, areas. Whether a residential real estate transaction being closed at title company prices, planning for the future of a business or estate, or a complex civil litigation case, our attorneys are focused on getting the job done efficiently and meeting client expectations and time deadlines.
Aside from being a full-service commercial and residential law firm, St. Johns Law Group also serves as City Attorney for the City of St. Augustine Beach and General Counsel for the Airport Authority. We understand the dynamics of St. Augustine Beach, Florida.


text:
← Frankenstein au National Theatre
La Disparue de Deauville (2007) →
Frankenstein at the National Theatre
Publié le août 31, 2013 par Dorothée
Directed by Dany Boyle (Review written in October 2012)
Mr. Cumberbatch as the Creature
So, yesterday evening, I went to a cinema more than an hour from my place to see the film version of the theatre play « Frankenstein » with Mr. Cumberbatch as the Creature.
First, I have to admit, I don't like Frankenstein. Well, I don't like the book. I think there is too much description, and the constant snivelling of the doctor who try to justify himself get on my nerves. I like the idea of the book, man against God, the scientific creation and its risks… And, I tought as a play, it could be interesting more visual, and with talented actors…
What can I say? It was just perfect.
Danny Boyle and his writer, Nick Dear, wanted to adopt the point of view of the creature, and It a bloody good idea!
And seeing it more than reading it, it's really different… Yes, IT'S ALIVE !
So, now, the performance in itself.
Be careful, it may be spoiliers in the following lines…
The « womb » from which the creature appears is a really good idea, the few minutes of fighting between the newborn and its new life is breathtaking. It seems like a real birth, difficult, or a fight for life, Mr. C's performance is amazing, from these first minutes to the end. the way he moves, the way the creature evolve from this muet wild thing who crawls on the floor to a educated, agile, intelligent human being capable of feelings, good and bad… Because, the interresting thing is that Frankenstein creates a human being. As the creature says, itwas made for love, just wait to be loved and it receives only hate, so it became a hater, a liar, a murderer… like humans beings (don't scream, it's a general talk, but unlike the French philosopher J.J Rousseau, I don't believe in the myth of the good wild man…)
in the play, which isn't narrated by Frankenstein, or the creature (or the sailor from the book who just dissapears; good idea! he's not needed in the plot!) we could see the reality of the character. the pride of Frankenstein who want to be God (stronger than god) and works for his pride and own glory, no just for science! We could empathize with the creature, rejected, hated and so human – in a good way this time! – because it just wants to be love, he just wants to be warm, to have enough food, to not be alone and lonely. Even after Elisabeth's murder (and rape… I wasn't happy with this addition, but I could understand it, and the self-hatred of the creature just after), you empathize with him, because Frankenstein was the sinner! He created life and abandonned it the second after! He just offered one lesson to his creation: rejection…
But I even have some pity for Frankenstein at the end (I think because of the play, and the acting of Jonny Lee Miller), he neither doesn't know really what love is, he is so a cold scientic mind, he was in a way abandonned too in his dreams of greatness and could see the happiness was just, well, Elisabeth! I dream he could have accomplished great things with his knowledge if he wasn't that childhish. and he could have accomplish great things with his creature… All this reflexions come from the way they have organized and play the story.
As for the play itself.. A lot of good actors, but, Mr. Cumberbatch is perfect. He has the best part ! Jonny Lee Miller is great too as the doctor, but I feel is acting a little aggressive, again, I wait for the other version… His Frankenstein is really cold, but so interresting, less childish than in the novel.
The scenery is purely amazing! Not many things on stage, but the sky… such a good idea! and I love the simple stage set, who permits to concentrated on the acting, but which keep the illusion (the house of Frankenstein's father, and the fisherman cottage for exemple). I love the empty hole they use to symbolised the mountains where Victor and the Creature had their first meeting.
Showing the creature's bride is too a good idea, it's much crueller when Frankenstein distroys her, like a murder, and it's an announcement of Elisabeth's murder. A little bit like if Frankenstein is also his own creature (I don't know if you follow me on this… he is another monster he has created)
The chat between the creature and Elisabeth is moving (nothing like this in the novel), all the more because he's about to kill her, and she is the only one (except the blind all man – but there were the blindness) to accept him. But it was too late… And even if « Frankenstein » is a tragedy, there is some fun parts, who lighted the tension, some very good lines and fun.
Mr Miller as the creature :
We have lost something… The spell of the first time! So, this will be more about the 2 different performances of the actors than about the play itself.
It was still a bliss! All the cast is amazing and I love the scenography (I love the sky! all this bulbs… such a inspired idea). The switching of the parts is obvious from the first minute. JLM has choosen to be a more childish monster. It's a kid who emerges from the womb. For BC it is longer and more difficult, it is a fight with a anormal life which appears. I much more prefer this first version as it sticks with my idea of the « creation » of the monster and as it prefigures what will be the life of the monster. Then, I think the approach of Cumberbatch is stronger, because the monster is not a newborn, but a victim of an experiment, so his way of moving at the begining (which remains to the end, but in a more discreet way), like AVC or accidents victims is a very good choice.
A scene is important for me concerning this difference of approach, it's when Elisabeth and the creature sit on the bed. BC continues to move his hands and legs with a small shaking, but JLM has his hands still on his legs. I feel as there is an evolution on the way of speaking of Cumberbatch's creature more important than Miller's.
I don't want to critize Miller, because he's great. His creature is more childish at the beginning, and more angry after, and maybe if I had seen his version first I would be less critic. But, I prefer Benedict Cumberbatch's creature. And, yes, I prefer his doctor, nearly for the same reason. Miller's doctor was really angry, Cumberbatch has moments of anger, but gentle moments too.
I really love the final scene of the second version, as BC is gentler than Miller. Yes, it's really my point, not that the creature (or Victor) is not authorized to be angry. It has all the reason in the world to be, but I prefer a more subtil approach. I feel that BC's performance as the creature is exceptionnal.
For the fun, I have a bliss moment when Elisabeth says to Victor « People are dull », and Mr. Cumberbatch can't hold a smile (he has hidden it very quicky). Naomi Harris's face was on screen at the moment, but the short pause before the words, and the smile… I'm sure she did it on purpose, and It a brilliant exemple of how theatre people could be playful even with a camera is around.
To conclude, I prefer the first version, but the second as the same quality. Brilliants actors, smart writing,amazing scenery. I think Nick Dear and Danny Boyle have really found the essence of the novel.
En Français : ICI
Posté dans theatre | Tagué Benedict Cumberbatch, Danny Boyle, Frankenstein, Jonny Lee Miller, National Theatre, nick Dear
Une réflexion sur "Frankenstein at the National Theatre"
Pingback: Frankenstein au National Theatre | Les Livres, Mes Livres & Moi


Eco Metal Recycling Inc. is one of Ontario's premier dismantling contractors serving the industrial Waterloo community. We have a long history of successfully and dependably providing the highest quality service. At Eco Metal Recycling, safety and Recycling the ECO way is our number one priority.
Our management team has over fifty years of combined experience in the dismantling and surplus process equipment business in Waterloo area. We are a single source provider for dismantling, asbestos abatement, environmental remediation, plant and equipment relocation, and plant purchases. Contact us at Eco Metal Recycling Inc. when you are planning your next project. We can help create solutions that will assure completion of your project on-time, on-budget, and on-target every time.
We can handle a variety of technically challenging and complex projects - serving industrial, government, and commercial clients in and around Waterloo, Ontario.
Here are a few reasons why Eco Metal Recycling Inc is the best Industrial demolition and dismantling company to use for Industrial decommissioning, plant relocation and plant equipment removal in Waterloo, Ontario area.
Contact us today for a free consultation or quote for a Factory/Industrial Dismantling project. It would be our pleasure to serve our Waterloo clients today!