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