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