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