Ejemplo n.º 1
0
std::vector<std::pair<SymbolRef, uint64_t>>
llvm::object::computeSymbolSizes(const ObjectFile &O) {
  std::vector<std::pair<SymbolRef, uint64_t>> Ret;

  if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) {
    auto Syms = E->symbols();
    if (Syms.begin() == Syms.end())
      Syms = E->getDynamicSymbolIterators();
    for (ELFSymbolRef Sym : Syms)
      Ret.push_back({Sym, Sym.getSize()});
    return Ret;
  }

  // Collect sorted symbol addresses. Include dummy addresses for the end
  // of each section.
  std::vector<SymEntry> Addresses;
  unsigned SymNum = 0;
  for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) {
    SymbolRef Sym = *I;
    uint64_t Value = Sym.getValue();
    Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)});
    ++SymNum;
  }
  for (SectionRef Sec : O.sections()) {
    uint64_t Address = Sec.getAddress();
    uint64_t Size = Sec.getSize();
    Addresses.push_back(
        {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)});
  }
  array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress);

  // Compute the size as the gap to the next symbol
  for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) {
    auto &P = Addresses[I];
    if (P.I == O.symbol_end())
      continue;

    // If multiple symbol have the same address, give both the same size.
    unsigned NextI = I + 1;
    while (NextI < N && Addresses[NextI].Address == P.Address)
      ++NextI;

    uint64_t Size = Addresses[NextI].Address - P.Address;
    P.Address = Size;
  }

  // Assign the sorted symbols in the original order.
  Ret.resize(SymNum);
  for (SymEntry &P : Addresses) {
    if (P.I == O.symbol_end())
      continue;
    Ret[P.Number] = {*P.I, P.Address};
  }
  return Ret;
}
Ejemplo n.º 2
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);
}