Example #1
0
static std::map<void *, uint64_t>
applySpecificSectionMappings(RuntimeDyldChecker &Checker) {

  std::map<void*, uint64_t> SpecificMappings;

  for (StringRef Mapping : SpecificSectionMappings) {

    size_t EqualsIdx = Mapping.find_first_of("=");
    StringRef SectionIDStr = Mapping.substr(0, EqualsIdx);
    size_t ComaIdx = Mapping.find_first_of(",");

    if (ComaIdx == StringRef::npos) {
      errs() << "Invalid section specification '" << Mapping
             << "'. Should be '<file name>,<section name>=<addr>'\n";
      exit(1);
    }

    StringRef FileName = SectionIDStr.substr(0, ComaIdx);
    StringRef SectionName = SectionIDStr.substr(ComaIdx + 1);

    uint64_t OldAddrInt;
    std::string ErrorMsg;
    std::tie(OldAddrInt, ErrorMsg) =
      Checker.getSectionAddr(FileName, SectionName, true);

    if (ErrorMsg != "") {
      errs() << ErrorMsg;
      exit(1);
    }

    void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt));

    StringRef NewAddrStr = Mapping.substr(EqualsIdx + 1);
    uint64_t NewAddr;

    if (NewAddrStr.getAsInteger(0, NewAddr)) {
      errs() << "Invalid section address in mapping: " << Mapping << "\n";
      exit(1);
    }

    Checker.getRTDyld().mapSectionAddress(OldAddr, NewAddr);
    SpecificMappings[OldAddr] = NewAddr;
  }

  return SpecificMappings;
}
Example #2
0
static int checkAllExpressions(RuntimeDyldChecker &Checker) {
  for (const auto& CheckerFileName : CheckFiles) {
    ErrorOr<std::unique_ptr<MemoryBuffer>> CheckerFileBuf =
        MemoryBuffer::getFileOrSTDIN(CheckerFileName);
    if (std::error_code EC = CheckerFileBuf.getError())
      return Error("unable to read input '" + CheckerFileName + "': " +
                   EC.message());

    if (!Checker.checkAllRulesInBuffer("# rtdyld-check:",
                                       CheckerFileBuf.get().get()))
      return Error("some checks in '" + CheckerFileName + "' failed");
  }
  return 0;
}
Example #3
0
// Scatter sections in all directions!
// Remaps section addresses for -verify mode. The following command line options
// can be used to customize the layout of the memory within the phony target's
// address space:
// -target-addr-start <s> -- Specify where the phony target addres range starts.
// -target-addr-end   <e> -- Specify where the phony target address range ends.
// -target-section-sep <d> -- Specify how big a gap should be left between the
//                            end of one section and the start of the next.
//                            Defaults to zero. Set to something big
//                            (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
//
static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
                                    TrivialMemoryManager &MemMgr,
                                    RuntimeDyldChecker &Checker) {

  // Set up a work list (section addr/size pairs).
  typedef std::list<std::pair<void*, uint64_t>> WorklistT;
  WorklistT Worklist;

  for (const auto& CodeSection : MemMgr.FunctionMemory)
    Worklist.push_back(std::make_pair(CodeSection.base(), CodeSection.size()));
  for (const auto& DataSection : MemMgr.DataMemory)
    Worklist.push_back(std::make_pair(DataSection.base(), DataSection.size()));

  // Apply any section-specific mappings that were requested on the command
  // line.
  typedef std::map<void*, uint64_t> AppliedMappingsT;
  AppliedMappingsT AppliedMappings = applySpecificSectionMappings(Checker);

  // Keep an "already allocated" mapping of section target addresses to sizes.
  // Sections whose address mappings aren't specified on the command line will
  // allocated around the explicitly mapped sections while maintaining the
  // minimum separation.
  std::map<uint64_t, uint64_t> AlreadyAllocated;

  // Move the previously applied mappings into the already-allocated map.
  for (WorklistT::iterator I = Worklist.begin(), E = Worklist.end();
       I != E;) {
    WorklistT::iterator Tmp = I;
    ++I;
    AppliedMappingsT::iterator AI = AppliedMappings.find(Tmp->first);

    if (AI != AppliedMappings.end()) {
      AlreadyAllocated[AI->second] = Tmp->second;
      Worklist.erase(Tmp);
    }
  }

  // If the -target-addr-end option wasn't explicitly passed, then set it to a
  // sensible default based on the target triple.
  if (TargetAddrEnd.getNumOccurrences() == 0) {
    if (TargetTriple.isArch16Bit())
      TargetAddrEnd = (1ULL << 16) - 1;
    else if (TargetTriple.isArch32Bit())
      TargetAddrEnd = (1ULL << 32) - 1;
    // TargetAddrEnd already has a sensible default for 64-bit systems, so
    // there's nothing to do in the 64-bit case.
  }

  // Process any elements remaining in the worklist.
  while (!Worklist.empty()) {
    std::pair<void*, uint64_t> CurEntry = Worklist.front();
    Worklist.pop_front();

    uint64_t NextSectionAddr = TargetAddrStart;

    for (const auto &Alloc : AlreadyAllocated)
      if (NextSectionAddr + CurEntry.second + TargetSectionSep <= Alloc.first)
        break;
      else
        NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep;

    AlreadyAllocated[NextSectionAddr] = CurEntry.second;
    Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr);
  }

  // Add dummy symbols to the memory manager.
  for (const auto &Mapping : DummySymbolMappings) {
    size_t EqualsIdx = Mapping.find_first_of("=");

    if (EqualsIdx == StringRef::npos)
      report_fatal_error("Invalid dummy symbol specification '" + Mapping +
                         "'. Should be '<symbol name>=<addr>'");

    std::string Symbol = Mapping.substr(0, EqualsIdx);
    std::string AddrStr = Mapping.substr(EqualsIdx + 1);

    uint64_t Addr;
    if (StringRef(AddrStr).getAsInteger(0, Addr))
      report_fatal_error("Invalid symbol mapping '" + Mapping + "'.");

    MemMgr.addDummySymbol(Symbol, Addr);
  }
}