xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp (revision 29f37e9bcc67d5d94c9d6bbbcf2717e16bf25c4e)
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  
18  using namespace llvm;
19  using namespace object;
20  
21  int 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