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