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