| //===- TestingSupport.cpp - Convert objects files into test files --------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Object/ObjectFile.h" |
| #include "llvm/ProfileData/InstrProf.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/LEB128.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <functional> |
| #include <system_error> |
| |
| using namespace llvm; |
| using namespace object; |
| |
| int convertForTestingMain(int argc, const char *argv[]) { |
| cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required, |
| cl::desc("<Source file>")); |
| |
| cl::opt<std::string> OutputFilename( |
| "o", cl::Required, |
| cl::desc( |
| "File with the profile data obtained after an instrumented run")); |
| |
| cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); |
| |
| auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile); |
| if (!ObjErr) { |
| std::string Buf; |
| raw_string_ostream OS(Buf); |
| logAllUnhandledErrors(ObjErr.takeError(), OS, ""); |
| OS.flush(); |
| errs() << "error: " << Buf; |
| return 1; |
| } |
| ObjectFile *OF = ObjErr.get().getBinary(); |
| auto BytesInAddress = OF->getBytesInAddress(); |
| if (BytesInAddress != 8) { |
| errs() << "error: 64 bit binary expected\n"; |
| return 1; |
| } |
| |
| // Look for the sections that we are interested in. |
| int FoundSectionCount = 0; |
| SectionRef ProfileNames, CoverageMapping; |
| auto ObjFormat = OF->getTripleObjectFormat(); |
| for (const auto &Section : OF->sections()) { |
| StringRef Name; |
| if (Section.getName(Name)) |
| return 1; |
| if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat, |
| /*AddSegmentInfo=*/false)) { |
| ProfileNames = Section; |
| } else if (Name == llvm::getInstrProfSectionName( |
| IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) { |
| CoverageMapping = Section; |
| } else |
| continue; |
| ++FoundSectionCount; |
| } |
| if (FoundSectionCount != 2) |
| return 1; |
| |
| // Get the contents of the given sections. |
| uint64_t ProfileNamesAddress = ProfileNames.getAddress(); |
| StringRef CoverageMappingData; |
| StringRef ProfileNamesData; |
| if (CoverageMapping.getContents(CoverageMappingData) || |
| ProfileNames.getContents(ProfileNamesData)) |
| return 1; |
| |
| int FD; |
| if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) { |
| errs() << "error: " << Err.message() << "\n"; |
| return 1; |
| } |
| |
| raw_fd_ostream OS(FD, true); |
| OS << "llvmcovmtestdata"; |
| encodeULEB128(ProfileNamesData.size(), OS); |
| encodeULEB128(ProfileNamesAddress, OS); |
| OS << ProfileNamesData; |
| // Coverage mapping data is expected to have an alignment of 8. |
| for (unsigned Pad = OffsetToAlignment(OS.tell(), 8); Pad; --Pad) |
| OS.write(uint8_t(0)); |
| OS << CoverageMappingData; |
| |
| return 0; |
| } |