brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 8eb8f8a Raw
147 lines · cpp
1//===- bolt/unittest/Core/MemoryMaps.cpp ----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "bolt/Core/BinaryContext.h"10#include "bolt/Profile/DataAggregator.h"11#include "llvm/BinaryFormat/ELF.h"12#include "llvm/DebugInfo/DWARF/DWARFContext.h"13#include "llvm/Support/CommandLine.h"14#include "llvm/Support/TargetSelect.h"15#include "llvm/Testing/Support/Error.h"16#include "gtest/gtest.h"17 18using namespace llvm;19using namespace llvm::object;20using namespace llvm::ELF;21using namespace bolt;22 23namespace opts {24extern cl::opt<std::string> ReadPerfEvents;25} // namespace opts26 27namespace {28 29/// Perform checks on memory map events normally captured in perf. Tests use30/// the 'opts::ReadPerfEvents' flag to emulate these events, passing a custom31/// 'perf script' output to DataAggregator.32struct MemoryMapsTester : public testing::TestWithParam<Triple::ArchType> {33  void SetUp() override {34    initalizeLLVM();35    prepareElf();36    initializeBOLT();37  }38 39protected:40  void initalizeLLVM() {41#define BOLT_TARGET(target)                                                    \42  LLVMInitialize##target##TargetInfo();                                        \43  LLVMInitialize##target##TargetMC();                                          \44  LLVMInitialize##target##AsmParser();                                         \45  LLVMInitialize##target##Disassembler();                                      \46  LLVMInitialize##target##Target();                                            \47  LLVMInitialize##target##AsmPrinter();48 49#include "bolt/Core/TargetConfig.def"50  }51 52  void prepareElf() {53    memcpy(ElfBuf, "\177ELF", 4);54    ELF64LE::Ehdr *EHdr = reinterpret_cast<typename ELF64LE::Ehdr *>(ElfBuf);55    EHdr->e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;56    EHdr->e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;57    EHdr->e_machine = GetParam() == Triple::aarch64 ? EM_AARCH64 : EM_X86_64;58    MemoryBufferRef Source(StringRef(ElfBuf, sizeof(ElfBuf)), "ELF");59    ObjFile = cantFail(ObjectFile::createObjectFile(Source));60  }61 62  void initializeBOLT() {63    Relocation::Arch = ObjFile->makeTriple().getArch();64    BC = cantFail(BinaryContext::createBinaryContext(65        ObjFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),66        ObjFile->getFileName(), nullptr, true, DWARFContext::create(*ObjFile),67        {llvm::outs(), llvm::errs()}));68    ASSERT_FALSE(!BC);69  }70 71  char ElfBuf[sizeof(typename ELF64LE::Ehdr)] = {};72  std::unique_ptr<ObjectFile> ObjFile;73  std::unique_ptr<BinaryContext> BC;74};75} // namespace76 77#ifdef X86_AVAILABLE78 79INSTANTIATE_TEST_SUITE_P(X86, MemoryMapsTester,80                         ::testing::Values(Triple::x86_64));81 82#endif83 84#ifdef AARCH64_AVAILABLE85 86INSTANTIATE_TEST_SUITE_P(AArch64, MemoryMapsTester,87                         ::testing::Values(Triple::aarch64));88 89#endif90 91/// Check that the correct mmap size is computed when we have multiple text92/// segment mappings.93TEST_P(MemoryMapsTester, ParseMultipleSegments) {94  const int Pid = 1234;95  StringRef Filename = "BINARY";96  opts::ReadPerfEvents = formatv(97      "name       0 [000]     0.000000: PERF_RECORD_MMAP2 {0}/{0}: "98      "[0xabc0000000(0x1000000) @ 0x11c0000 103:01 1573523 0]: r-xp {1}\n"99      "name       0 [000]     0.000000: PERF_RECORD_MMAP2 {0}/{0}: "100      "[0xabc2000000(0x8000000) @ 0x31d0000 103:01 1573523 0]: r-xp {1}\n",101      Pid, Filename);102 103  BC->SegmentMapInfo[0x11da000] = SegmentInfo{104      0x11da000, 0x10da000, 0x11ca000, 0x10da000, 0x10000, true, false};105  BC->SegmentMapInfo[0x31d0000] = SegmentInfo{106      0x31d0000, 0x51ac82c, 0x31d0000, 0x3000000, 0x200000, true, false};107 108  DataAggregator DA("");109  BC->setFilename(Filename);110  Error Err = DA.preprocessProfile(*BC);111 112  // Ignore errors from perf2bolt when parsing memory events later on.113  ASSERT_THAT_ERROR(std::move(Err), Succeeded());114 115  auto &BinaryMMapInfo = DA.getBinaryMMapInfo();116  auto El = BinaryMMapInfo.find(Pid);117  // Check that memory mapping is present and has the expected size.118  ASSERT_NE(El, BinaryMMapInfo.end());119  ASSERT_EQ(El->second.Size, static_cast<uint64_t>(0xb1d0000));120}121 122/// Check that DataAggregator aborts when pre-processing an input binary123/// with multiple text segments that have different base addresses.124TEST_P(MemoryMapsTester, MultipleSegmentsMismatchedBaseAddress) {125  const int Pid = 1234;126  StringRef Filename = "BINARY";127  opts::ReadPerfEvents = formatv(128      "name       0 [000]     0.000000: PERF_RECORD_MMAP2 {0}/{0}: "129      "[0xabc0000000(0x1000000) @ 0x11c0000 103:01 1573523 0]: r-xp {1}\n"130      "name       0 [000]     0.000000: PERF_RECORD_MMAP2 {0}/{0}: "131      "[0xabc2000000(0x8000000) @ 0x31d0000 103:01 1573523 0]: r-xp {1}\n",132      Pid, Filename);133 134  BC->SegmentMapInfo[0x11da000] = SegmentInfo{135      0x11da000, 0x10da000, 0x11ca000, 0x10da000, 0x10000, true, false};136  // Using '0x31d0fff' FileOffset which triggers a different base address137  // for this second text segment.138  BC->SegmentMapInfo[0x31d0000] = SegmentInfo{139      0x31d0000, 0x51ac82c, 0x31d0fff, 0x3000000, 0x200000, true, false};140 141  DataAggregator DA("");142  BC->setFilename(Filename);143  ASSERT_DEBUG_DEATH(144      { Error Err = DA.preprocessProfile(*BC); },145      "Base address on multiple segment mappings should match");146}147