TestingSupport.cpp revision 360784
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Object/ObjectFile.h"
10#include "llvm/ProfileData/InstrProf.h"
11#include "llvm/Support/Alignment.h"
12#include "llvm/Support/CommandLine.h"
13#include "llvm/Support/LEB128.h"
14#include "llvm/Support/raw_ostream.h"
15#include <functional>
16#include <system_error>
17
18using namespace llvm;
19using namespace object;
20
21int convertForTestingMain(int argc, const char *argv[]) {
22  cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required,
23                                       cl::desc("<Source file>"));
24
25  cl::opt<std::string> OutputFilename(
26      "o", cl::Required,
27      cl::desc(
28          "File with the profile data obtained after an instrumented run"));
29
30  cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
31
32  auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile);
33  if (!ObjErr) {
34    std::string Buf;
35    raw_string_ostream OS(Buf);
36    logAllUnhandledErrors(ObjErr.takeError(), OS);
37    OS.flush();
38    errs() << "error: " << Buf;
39    return 1;
40  }
41  ObjectFile *OF = ObjErr.get().getBinary();
42  auto BytesInAddress = OF->getBytesInAddress();
43  if (BytesInAddress != 8) {
44    errs() << "error: 64 bit binary expected\n";
45    return 1;
46  }
47
48  // Look for the sections that we are interested in.
49  int FoundSectionCount = 0;
50  SectionRef ProfileNames, CoverageMapping;
51  auto ObjFormat = OF->getTripleObjectFormat();
52  for (const auto &Section : OF->sections()) {
53    StringRef Name;
54    if (Expected<StringRef> NameOrErr = Section.getName()) {
55      Name = *NameOrErr;
56    } else {
57      consumeError(NameOrErr.takeError());
58      return 1;
59    }
60
61    if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat,
62                                              /*AddSegmentInfo=*/false)) {
63      ProfileNames = Section;
64    } else if (Name == llvm::getInstrProfSectionName(
65                           IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) {
66      CoverageMapping = Section;
67    } else
68      continue;
69    ++FoundSectionCount;
70  }
71  if (FoundSectionCount != 2)
72    return 1;
73
74  // Get the contents of the given sections.
75  uint64_t ProfileNamesAddress = ProfileNames.getAddress();
76  StringRef CoverageMappingData;
77  StringRef ProfileNamesData;
78  if (Expected<StringRef> E = CoverageMapping.getContents())
79    CoverageMappingData = *E;
80  else {
81    consumeError(E.takeError());
82    return 1;
83  }
84  if (Expected<StringRef> E = ProfileNames.getContents())
85    ProfileNamesData = *E;
86  else {
87    consumeError(E.takeError());
88    return 1;
89  }
90
91  int FD;
92  if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {
93    errs() << "error: " << Err.message() << "\n";
94    return 1;
95  }
96
97  raw_fd_ostream OS(FD, true);
98  OS << "llvmcovmtestdata";
99  encodeULEB128(ProfileNamesData.size(), OS);
100  encodeULEB128(ProfileNamesAddress, OS);
101  OS << ProfileNamesData;
102  // Coverage mapping data is expected to have an alignment of 8.
103  for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
104    OS.write(uint8_t(0));
105  OS << CoverageMappingData;
106
107  return 0;
108}
109