Ejemplo n.º 1
0
// compute stub buffer size for the given section
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
                                                    const SectionRef &Section) {
  unsigned StubSize = getMaxStubSize();
  if (StubSize == 0) {
    return 0;
  }
  // FIXME: this is an inefficient way to handle this. We should computed the
  // necessary section allocation size in loadObject by walking all the sections
  // once.
  unsigned StubBufSize = 0;
  for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
       SI != SE; ++SI) {
    section_iterator RelSecI = SI->getRelocatedSection();
    if (!(RelSecI == Section))
      continue;

    for (const RelocationRef &Reloc : SI->relocations()) {
      (void)Reloc;
      StubBufSize += StubSize;
    }
  }

  // Get section data size and alignment
  uint64_t DataSize = Section.getSize();
  uint64_t Alignment64 = Section.getAlignment();

  // Add stubbuf size alignment
  unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
  unsigned StubAlignment = getStubAlignment();
  unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
  if (StubAlignment > EndAlignment)
    StubBufSize += StubAlignment - EndAlignment;
  return StubBufSize;
}
Ejemplo n.º 2
0
void ObjectLoadListener::recordRelocations(
    const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) {
  for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
       SI != SE; ++SI) {
    section_iterator Section = SI->getRelocatedSection();

    if (Section == SE) {
      continue;
    }

    StringRef SectionName;
    std::error_code ErrorCode = Section->getName(SectionName);
    if (ErrorCode) {
      assert(false && ErrorCode.message().c_str());
    }

    if (SectionName.startswith(".debug") ||
        SectionName.startswith(".rela.debug") ||
        !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") ||
        SectionName.startswith(".rela.eh_frame")) {
      // Skip sections whose contents are not directly reported to the EE
      continue;
    }

    relocation_iterator I = SI->relocation_begin();
    relocation_iterator E = SI->relocation_end();

    for (; I != E; ++I) {
      symbol_iterator Symbol = I->getSymbol();
      assert(Symbol != Obj.symbol_end());
      ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection();
      assert(!SymbolSectionOrErr.getError());
      object::section_iterator SymbolSection = *SymbolSectionOrErr;
      const bool IsExtern = SymbolSection == Obj.section_end();
      uint64_t RelType = I->getType();
      uint64_t Offset = I->getOffset();
      uint8_t *RelocationTarget;
      if (IsExtern) {
        // This is an external symbol. Verify that it's one we created for
        // a global variable and report the relocation via Jit interface.
        ErrorOr<StringRef> NameOrError = Symbol->getName();
        assert(NameOrError);
        StringRef TargetName = NameOrError.get();
        auto MapIter = Context->NameToHandleMap.find(TargetName);
        if (MapIter == Context->NameToHandleMap.end()) {
          // The xdata gets a pointer to our personality routine, which we
          // dummied up.  We can safely skip it since the EE isn't actually
          // going to use the value (it inserts the correct one before handing
          // the xdata off to the OS).
          assert(!TargetName.compare("ProcessCLRException"));
          assert(SectionName.startswith(".xdata"));
          continue;
        } else {
          assert(MapIter->second == Context->NameToHandleMap[TargetName]);
          RelocationTarget = (uint8_t *)MapIter->second;
        }
      } else {
        RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) +
                                       Symbol->getValue());
      }

      uint64_t Addend = 0;
      uint64_t EERelType = getRelocationType(RelType);
      uint64_t SectionAddress = L.getSectionLoadAddress(*Section);
      assert(SectionAddress != 0);
      uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset);

      if (Obj.isELF()) {
        // Addend is part of the relocation
        ELFRelocationRef ElfReloc(*I);
        ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend();
        assert(!ElfAddend.getError());
        Addend = ElfAddend.get();
      } else {
        // Addend is read from the location to be fixed up
        Addend = getRelocationAddend(RelType, FixupAddress);
      }

      Context->JitInfo->recordRelocation(FixupAddress,
                                         RelocationTarget + Addend, EERelType);
    }
  }
}
Ejemplo n.º 3
0
// Compute an upper bound of the memory size that is required to load all
// sections
void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
                                            uint64_t &CodeSize,
                                            uint64_t &DataSizeRO,
                                            uint64_t &DataSizeRW) {
  // Compute the size of all sections required for execution
  std::vector<uint64_t> CodeSectionSizes;
  std::vector<uint64_t> ROSectionSizes;
  std::vector<uint64_t> RWSectionSizes;
  uint64_t MaxAlignment = sizeof(void *);

  // Collect sizes of all sections to be loaded;
  // also determine the max alignment of all sections
  for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
       SI != SE; ++SI) {
    const SectionRef &Section = *SI;

    bool IsRequired = Section.isRequiredForExecution();

    // Consider only the sections that are required to be loaded for execution
    if (IsRequired) {
      StringRef Name;
      uint64_t DataSize = Section.getSize();
      uint64_t Alignment64 = Section.getAlignment();
      bool IsCode = Section.isText();
      bool IsReadOnly = Section.isReadOnlyData();
      Check(Section.getName(Name));
      unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;

      uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
      uint64_t SectionSize = DataSize + StubBufSize;

      // The .eh_frame section (at least on Linux) needs an extra four bytes
      // padded
      // with zeroes added at the end.  For MachO objects, this section has a
      // slightly different name, so this won't have any effect for MachO
      // objects.
      if (Name == ".eh_frame")
        SectionSize += 4;

      if (SectionSize > 0) {
        // save the total size of the section
        if (IsCode) {
          CodeSectionSizes.push_back(SectionSize);
        } else if (IsReadOnly) {
          ROSectionSizes.push_back(SectionSize);
        } else {
          RWSectionSizes.push_back(SectionSize);
        }
        // update the max alignment
        if (Alignment > MaxAlignment) {
          MaxAlignment = Alignment;
        }
      }
    }
  }

  // Compute the size of all common symbols
  uint64_t CommonSize = 0;
  for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E;
       ++I) {
    uint32_t Flags = I->getFlags();
    if (Flags & SymbolRef::SF_Common) {
      // Add the common symbols to a list.  We'll allocate them all below.
      uint64_t Size = 0;
      Check(I->getSize(Size));
      CommonSize += Size;
    }
  }
  if (CommonSize != 0) {
    RWSectionSizes.push_back(CommonSize);
  }

  // Compute the required allocation space for each different type of sections
  // (code, read-only data, read-write data) assuming that all sections are
  // allocated with the max alignment. Note that we cannot compute with the
  // individual alignments of the sections, because then the required size
  // depends on the order, in which the sections are allocated.
  CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment);
  DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment);
  DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment);
}
Ejemplo n.º 4
0
void ObjectLoadListener::recordRelocations(
    const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) {
  for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
       SI != SE; ++SI) {
    section_iterator Section = SI->getRelocatedSection();

    if (Section == SE) {
      continue;
    }

    StringRef SectionName;
    std::error_code ErrorCode = Section->getName(SectionName);
    if (ErrorCode) {
      assert(false && ErrorCode.message().c_str());
    }

    if (SectionName.startswith(".debug") ||
        SectionName.startswith(".rela.debug") ||
        !SectionName.compare(".pdata") || SectionName.startswith(".eh_frame") ||
        SectionName.startswith(".rela.eh_frame")) {
      // Skip sections whose contents are not directly reported to the EE
      continue;
    }

    relocation_iterator I = SI->relocation_begin();
    relocation_iterator E = SI->relocation_end();

    for (; I != E; ++I) {
      symbol_iterator Symbol = I->getSymbol();
      assert(Symbol != Obj.symbol_end());
      ErrorOr<section_iterator> SymbolSectionOrErr = Symbol->getSection();
      assert(!SymbolSectionOrErr.getError());
      object::section_iterator SymbolSection = *SymbolSectionOrErr;
      const bool IsExtern = SymbolSection == Obj.section_end();
      uint64_t RelType = I->getType();
      uint64_t Offset = I->getOffset();
      uint8_t *RelocationTarget = nullptr;
      if (IsExtern) {
        // This is an external symbol. Verify that it's one we created for
        // a global variable and report the relocation via Jit interface.
        ErrorOr<StringRef> NameOrError = Symbol->getName();
        assert(NameOrError);
        StringRef TargetName = NameOrError.get();
        assert(Context->NameToHandleMap.count(TargetName) == 1);
        RelocationTarget = (uint8_t *)Context->NameToHandleMap[TargetName];
      } else {
        RelocationTarget = (uint8_t *)(L.getSectionLoadAddress(*SymbolSection) +
                                       Symbol->getValue());
      }

      uint64_t Addend = 0;
      uint64_t EERelType = getRelocationType(RelType);
      uint64_t SectionAddress = L.getSectionLoadAddress(*Section);
      assert(SectionAddress != 0);
      uint8_t *FixupAddress = (uint8_t *)(SectionAddress + Offset);

      if (Obj.isELF()) {
        // Addend is part of the relocation
        ELFRelocationRef ElfReloc(*I);
        ErrorOr<uint64_t> ElfAddend = ElfReloc.getAddend();
        assert(!ElfAddend.getError());
        Addend = ElfAddend.get();
      } else {
        // Addend is read from the location to be fixed up
        Addend = getRelocationAddend(RelType, FixupAddress);
      }

      Context->JitInfo->recordRelocation(FixupAddress,
                                         RelocationTarget + Addend, EERelType);
    }
  }
}