brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 6ad8c35 Raw
143 lines · cpp
1//===- TestingSupport.cpp - Convert objects files into test files --------===//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 "llvm/Object/COFF.h"10#include "llvm/Object/ObjectFile.h"11#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"12#include "llvm/ProfileData/InstrProf.h"13#include "llvm/Support/Alignment.h"14#include "llvm/Support/CommandLine.h"15#include "llvm/Support/FileSystem.h"16#include "llvm/Support/LEB128.h"17#include "llvm/Support/MemoryBuffer.h"18#include "llvm/Support/raw_ostream.h"19#include <functional>20#include <system_error>21 22using namespace llvm;23using namespace object;24 25int convertForTestingMain(int argc, const char *argv[]) {26  cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required,27                                       cl::desc("<Source file>"));28 29  cl::opt<std::string> OutputFilename(30      "o", cl::Required,31      cl::desc(32          "File with the profile data obtained after an instrumented run"));33 34  cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");35 36  auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile);37  if (!ObjErr) {38    std::string Buf;39    raw_string_ostream OS(Buf);40    logAllUnhandledErrors(ObjErr.takeError(), OS);41    OS.flush();42    errs() << "error: " << Buf;43    return 1;44  }45  ObjectFile *OF = ObjErr.get().getBinary();46  auto BytesInAddress = OF->getBytesInAddress();47  if (BytesInAddress != 8) {48    errs() << "error: 64 bit binary expected\n";49    return 1;50  }51 52  // Look for the sections that we are interested in.53  int FoundSectionCount = 0;54  SectionRef ProfileNames, CoverageMapping, CoverageRecords;55  auto ObjFormat = OF->getTripleObjectFormat();56 57  auto ProfileNamesSection = getInstrProfSectionName(IPSK_name, ObjFormat,58                                                     /*AddSegmentInfo=*/false);59  auto CoverageMappingSection =60      getInstrProfSectionName(IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false);61  auto CoverageRecordsSection =62      getInstrProfSectionName(IPSK_covfun, ObjFormat, /*AddSegmentInfo=*/false);63  if (isa<object::COFFObjectFile>(OF)) {64    // On COFF, the object file section name may end in "$M". This tells the65    // linker to sort these sections between "$A" and "$Z". The linker removes66    // the dollar and everything after it in the final binary. Do the same to67    // match.68    auto Strip = [](std::string &Str) {69      auto Pos = Str.find('$');70      if (Pos != std::string::npos)71        Str.resize(Pos);72    };73    Strip(ProfileNamesSection);74    Strip(CoverageMappingSection);75    Strip(CoverageRecordsSection);76  }77 78  for (const auto &Section : OF->sections()) {79    StringRef Name;80    if (Expected<StringRef> NameOrErr = Section.getName()) {81      Name = *NameOrErr;82    } else {83      consumeError(NameOrErr.takeError());84      return 1;85    }86 87    if (Name == ProfileNamesSection)88      ProfileNames = Section;89    else if (Name == CoverageMappingSection)90      CoverageMapping = Section;91    else if (Name == CoverageRecordsSection)92      CoverageRecords = Section;93    else94      continue;95    ++FoundSectionCount;96  }97  if (FoundSectionCount != 3)98    return 1;99 100  // Get the contents of the given sections.101  uint64_t ProfileNamesAddress = ProfileNames.getAddress();102  StringRef CoverageMappingData;103  StringRef CoverageRecordsData;104  StringRef ProfileNamesData;105  if (Expected<StringRef> E = CoverageMapping.getContents())106    CoverageMappingData = *E;107  else {108    consumeError(E.takeError());109    return 1;110  }111  if (Expected<StringRef> E = CoverageRecords.getContents())112    CoverageRecordsData = *E;113  else {114    consumeError(E.takeError());115    return 1;116  }117  if (Expected<StringRef> E = ProfileNames.getContents())118    ProfileNamesData = *E;119  else {120    consumeError(E.takeError());121    return 1;122  }123 124  // If this is a linked PE/COFF file, then we have to skip over the null byte125  // that is allocated in the .lprfn$A section in the LLVM profiling runtime.126  if (isa<COFFObjectFile>(OF) && !OF->isRelocatableObject())127    ProfileNamesData = ProfileNamesData.drop_front(1);128 129  int FD;130  if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {131    errs() << "error: " << Err.message() << "\n";132    return 1;133  }134 135  coverage::TestingFormatWriter Writer(ProfileNamesAddress, ProfileNamesData,136                                       CoverageMappingData,137                                       CoverageRecordsData);138  raw_fd_ostream OS(FD, true);139  Writer.write(OS);140 141  return 0;142}143