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