[clang][NFC] simplify the unset check in `ParseLabeledStatement` (#117430)
[llvm-project.git] / llvm / tools / llvm-cov / TestingSupport.cpp
blob6ad8c35d6e12f87fb75fafdfb4a553f53031596e
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 //===----------------------------------------------------------------------===//
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>
22 using namespace llvm;
23 using namespace object;
25 int convertForTestingMain(int argc, const char *argv[]) {
26 cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required,
27 cl::desc("<Source file>"));
29 cl::opt<std::string> OutputFilename(
30 "o", cl::Required,
31 cl::desc(
32 "File with the profile data obtained after an instrumented run"));
34 cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
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;
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;
52 // Look for the sections that we are interested in.
53 int FoundSectionCount = 0;
54 SectionRef ProfileNames, CoverageMapping, CoverageRecords;
55 auto ObjFormat = OF->getTripleObjectFormat();
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 the
65 // linker to sort these sections between "$A" and "$Z". The linker removes
66 // the dollar and everything after it in the final binary. Do the same to
67 // match.
68 auto Strip = [](std::string &Str) {
69 auto Pos = Str.find('$');
70 if (Pos != std::string::npos)
71 Str.resize(Pos);
73 Strip(ProfileNamesSection);
74 Strip(CoverageMappingSection);
75 Strip(CoverageRecordsSection);
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;
87 if (Name == ProfileNamesSection)
88 ProfileNames = Section;
89 else if (Name == CoverageMappingSection)
90 CoverageMapping = Section;
91 else if (Name == CoverageRecordsSection)
92 CoverageRecords = Section;
93 else
94 continue;
95 ++FoundSectionCount;
97 if (FoundSectionCount != 3)
98 return 1;
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;
111 if (Expected<StringRef> E = CoverageRecords.getContents())
112 CoverageRecordsData = *E;
113 else {
114 consumeError(E.takeError());
115 return 1;
117 if (Expected<StringRef> E = ProfileNames.getContents())
118 ProfileNamesData = *E;
119 else {
120 consumeError(E.takeError());
121 return 1;
124 // If this is a linked PE/COFF file, then we have to skip over the null byte
125 // 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);
129 int FD;
130 if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {
131 errs() << "error: " << Err.message() << "\n";
132 return 1;
135 coverage::TestingFormatWriter Writer(ProfileNamesAddress, ProfileNamesData,
136 CoverageMappingData,
137 CoverageRecordsData);
138 raw_fd_ostream OS(FD, true);
139 Writer.write(OS);
141 return 0;