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" 11af11cc7eSGuillaume Chatelet #include "llvm/Support/Alignment.h" 12e82d89ccSAlex Lorenz #include "llvm/Support/CommandLine.h" 13*ba7a92c0SNico Weber #include "llvm/Support/FileSystem.h" 14d9903888SChandler Carruth #include "llvm/Support/LEB128.h" 15d9903888SChandler Carruth #include "llvm/Support/raw_ostream.h" 16e82d89ccSAlex Lorenz #include <functional> 17d9903888SChandler Carruth #include <system_error> 18e82d89ccSAlex Lorenz 19e82d89ccSAlex Lorenz using namespace llvm; 20e82d89ccSAlex Lorenz using namespace object; 21e82d89ccSAlex Lorenz 22d249a3b3SJustin Bogner int convertForTestingMain(int argc, const char *argv[]) { 23e82d89ccSAlex Lorenz cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required, 24e82d89ccSAlex Lorenz cl::desc("<Source file>")); 25e82d89ccSAlex Lorenz 26e82d89ccSAlex Lorenz cl::opt<std::string> OutputFilename( 27e82d89ccSAlex Lorenz "o", cl::Required, 28e82d89ccSAlex Lorenz cl::desc( 29e82d89ccSAlex Lorenz "File with the profile data obtained after an instrumented run")); 30e82d89ccSAlex Lorenz 31e82d89ccSAlex Lorenz cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); 32e82d89ccSAlex Lorenz 33e82d89ccSAlex Lorenz auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile); 343fcdf6aeSKevin Enderby if (!ObjErr) { 353fcdf6aeSKevin Enderby std::string Buf; 363fcdf6aeSKevin Enderby raw_string_ostream OS(Buf); 3745eb84f3SJonas Devlieghere logAllUnhandledErrors(ObjErr.takeError(), OS); 383fcdf6aeSKevin Enderby OS.flush(); 393fcdf6aeSKevin Enderby errs() << "error: " << Buf; 40e82d89ccSAlex Lorenz return 1; 41e82d89ccSAlex Lorenz } 42f04de6ecSLang Hames ObjectFile *OF = ObjErr.get().getBinary(); 43e82d89ccSAlex Lorenz auto BytesInAddress = OF->getBytesInAddress(); 44e82d89ccSAlex Lorenz if (BytesInAddress != 8) { 45e82d89ccSAlex Lorenz errs() << "error: 64 bit binary expected\n"; 46e82d89ccSAlex Lorenz return 1; 47e82d89ccSAlex Lorenz } 48e82d89ccSAlex Lorenz 49e82d89ccSAlex Lorenz // Look for the sections that we are interested in. 50e82d89ccSAlex Lorenz int FoundSectionCount = 0; 51e82d89ccSAlex Lorenz SectionRef ProfileNames, CoverageMapping; 521a6a2b64SVedant Kumar auto ObjFormat = OF->getTripleObjectFormat(); 53e82d89ccSAlex Lorenz for (const auto &Section : OF->sections()) { 54e82d89ccSAlex Lorenz StringRef Name; 55bcc00e1aSGeorge Rimar if (Expected<StringRef> NameOrErr = Section.getName()) { 56bcc00e1aSGeorge Rimar Name = *NameOrErr; 57bcc00e1aSGeorge Rimar } else { 58bcc00e1aSGeorge Rimar consumeError(NameOrErr.takeError()); 59e82d89ccSAlex Lorenz return 1; 60bcc00e1aSGeorge Rimar } 61bcc00e1aSGeorge Rimar 621a6a2b64SVedant Kumar if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat, 631a6a2b64SVedant Kumar /*AddSegmentInfo=*/false)) { 64e82d89ccSAlex Lorenz ProfileNames = Section; 651a6a2b64SVedant Kumar } else if (Name == llvm::getInstrProfSectionName( 661a6a2b64SVedant Kumar IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) { 67e82d89ccSAlex Lorenz CoverageMapping = Section; 68e82d89ccSAlex Lorenz } else 69e82d89ccSAlex Lorenz continue; 70e82d89ccSAlex Lorenz ++FoundSectionCount; 71e82d89ccSAlex Lorenz } 72e82d89ccSAlex Lorenz if (FoundSectionCount != 2) 73e82d89ccSAlex Lorenz return 1; 74e82d89ccSAlex Lorenz 75e82d89ccSAlex Lorenz // Get the contents of the given sections. 7680291274SRafael Espindola uint64_t ProfileNamesAddress = ProfileNames.getAddress(); 77e82d89ccSAlex Lorenz StringRef CoverageMappingData; 78e82d89ccSAlex Lorenz StringRef ProfileNamesData; 79e183340cSFangrui Song if (Expected<StringRef> E = CoverageMapping.getContents()) 80e183340cSFangrui Song CoverageMappingData = *E; 81e183340cSFangrui Song else { 82e183340cSFangrui Song consumeError(E.takeError()); 83e82d89ccSAlex Lorenz return 1; 84e183340cSFangrui Song } 85e183340cSFangrui Song if (Expected<StringRef> E = ProfileNames.getContents()) 86e183340cSFangrui Song ProfileNamesData = *E; 87e183340cSFangrui Song else { 88e183340cSFangrui Song consumeError(E.takeError()); 89e183340cSFangrui Song return 1; 90e183340cSFangrui Song } 91e82d89ccSAlex Lorenz 92e82d89ccSAlex Lorenz int FD; 931f67a3cbSZachary Turner if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) { 94e82d89ccSAlex Lorenz errs() << "error: " << Err.message() << "\n"; 95e82d89ccSAlex Lorenz return 1; 96e82d89ccSAlex Lorenz } 97e82d89ccSAlex Lorenz 98e82d89ccSAlex Lorenz raw_fd_ostream OS(FD, true); 99e82d89ccSAlex Lorenz OS << "llvmcovmtestdata"; 100e82d89ccSAlex Lorenz encodeULEB128(ProfileNamesData.size(), OS); 101e82d89ccSAlex Lorenz encodeULEB128(ProfileNamesAddress, OS); 102eb103073SIgor Kudrin OS << ProfileNamesData; 103eb103073SIgor Kudrin // Coverage mapping data is expected to have an alignment of 8. 10418f805a7SGuillaume Chatelet for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad) 105eb103073SIgor Kudrin OS.write(uint8_t(0)); 106eb103073SIgor Kudrin OS << CoverageMappingData; 107e82d89ccSAlex Lorenz 108e82d89ccSAlex Lorenz return 0; 109e82d89ccSAlex Lorenz } 110