1*e82d89ccSAlex Lorenz //===- TestingSupport.cpp - Convert objects files into test files --------===//
2*e82d89ccSAlex Lorenz //
3*e82d89ccSAlex Lorenz //                     The LLVM Compiler Infrastructure
4*e82d89ccSAlex Lorenz //
5*e82d89ccSAlex Lorenz // This file is distributed under the University of Illinois Open Source
6*e82d89ccSAlex Lorenz // License. See LICENSE.TXT for details.
7*e82d89ccSAlex Lorenz //
8*e82d89ccSAlex Lorenz //===----------------------------------------------------------------------===//
9*e82d89ccSAlex Lorenz 
10*e82d89ccSAlex Lorenz #include "llvm/Object/ObjectFile.h"
11*e82d89ccSAlex Lorenz #include "llvm/Support/raw_ostream.h"
12*e82d89ccSAlex Lorenz #include "llvm/Support/LEB128.h"
13*e82d89ccSAlex Lorenz #include "llvm/Support/CommandLine.h"
14*e82d89ccSAlex Lorenz #include "llvm/Support/ManagedStatic.h"
15*e82d89ccSAlex Lorenz #include "llvm/Support/MemoryObject.h"
16*e82d89ccSAlex Lorenz #include "llvm/Support/Signals.h"
17*e82d89ccSAlex Lorenz #include "llvm/Support/PrettyStackTrace.h"
18*e82d89ccSAlex Lorenz #include <system_error>
19*e82d89ccSAlex Lorenz #include <functional>
20*e82d89ccSAlex Lorenz 
21*e82d89ccSAlex Lorenz using namespace llvm;
22*e82d89ccSAlex Lorenz using namespace object;
23*e82d89ccSAlex Lorenz 
24*e82d89ccSAlex Lorenz int convert_for_testing_main(int argc, const char **argv) {
25*e82d89ccSAlex Lorenz   sys::PrintStackTraceOnErrorSignal();
26*e82d89ccSAlex Lorenz   PrettyStackTraceProgram X(argc, argv);
27*e82d89ccSAlex Lorenz   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
28*e82d89ccSAlex Lorenz 
29*e82d89ccSAlex Lorenz   cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required,
30*e82d89ccSAlex Lorenz                                        cl::desc("<Source file>"));
31*e82d89ccSAlex Lorenz 
32*e82d89ccSAlex Lorenz   cl::opt<std::string> OutputFilename(
33*e82d89ccSAlex Lorenz       "o", cl::Required,
34*e82d89ccSAlex Lorenz       cl::desc(
35*e82d89ccSAlex Lorenz           "File with the profile data obtained after an instrumented run"));
36*e82d89ccSAlex Lorenz 
37*e82d89ccSAlex Lorenz   cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
38*e82d89ccSAlex Lorenz 
39*e82d89ccSAlex Lorenz   auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile);
40*e82d89ccSAlex Lorenz   if (auto Err = ObjErr.getError()) {
41*e82d89ccSAlex Lorenz     errs() << "error: " << Err.message() << "\n";
42*e82d89ccSAlex Lorenz     return 1;
43*e82d89ccSAlex Lorenz   }
44*e82d89ccSAlex Lorenz   ObjectFile *OF = ObjErr.get().getBinary().get();
45*e82d89ccSAlex Lorenz   auto BytesInAddress = OF->getBytesInAddress();
46*e82d89ccSAlex Lorenz   if (BytesInAddress != 8) {
47*e82d89ccSAlex Lorenz     errs() << "error: 64 bit binary expected\n";
48*e82d89ccSAlex Lorenz     return 1;
49*e82d89ccSAlex Lorenz   }
50*e82d89ccSAlex Lorenz 
51*e82d89ccSAlex Lorenz   // Look for the sections that we are interested in.
52*e82d89ccSAlex Lorenz   int FoundSectionCount = 0;
53*e82d89ccSAlex Lorenz   SectionRef ProfileNames, CoverageMapping;
54*e82d89ccSAlex Lorenz   for (const auto &Section : OF->sections()) {
55*e82d89ccSAlex Lorenz     StringRef Name;
56*e82d89ccSAlex Lorenz     if (Section.getName(Name))
57*e82d89ccSAlex Lorenz       return 1;
58*e82d89ccSAlex Lorenz     if (Name == "__llvm_prf_names") {
59*e82d89ccSAlex Lorenz       ProfileNames = Section;
60*e82d89ccSAlex Lorenz     } else if (Name == "__llvm_covmap") {
61*e82d89ccSAlex Lorenz       CoverageMapping = Section;
62*e82d89ccSAlex Lorenz     } else
63*e82d89ccSAlex Lorenz       continue;
64*e82d89ccSAlex Lorenz     ++FoundSectionCount;
65*e82d89ccSAlex Lorenz   }
66*e82d89ccSAlex Lorenz   if (FoundSectionCount != 2)
67*e82d89ccSAlex Lorenz     return 1;
68*e82d89ccSAlex Lorenz 
69*e82d89ccSAlex Lorenz   // Get the contents of the given sections.
70*e82d89ccSAlex Lorenz   StringRef CoverageMappingData;
71*e82d89ccSAlex Lorenz   uint64_t ProfileNamesAddress;
72*e82d89ccSAlex Lorenz   StringRef ProfileNamesData;
73*e82d89ccSAlex Lorenz   if (CoverageMapping.getContents(CoverageMappingData) ||
74*e82d89ccSAlex Lorenz       ProfileNames.getAddress(ProfileNamesAddress) ||
75*e82d89ccSAlex Lorenz       ProfileNames.getContents(ProfileNamesData))
76*e82d89ccSAlex Lorenz     return 1;
77*e82d89ccSAlex Lorenz 
78*e82d89ccSAlex Lorenz   int FD;
79*e82d89ccSAlex Lorenz   if (auto Err =
80*e82d89ccSAlex Lorenz           sys::fs::openFileForWrite(OutputFilename, FD, sys::fs::F_None)) {
81*e82d89ccSAlex Lorenz     errs() << "error: " << Err.message() << "\n";
82*e82d89ccSAlex Lorenz     return 1;
83*e82d89ccSAlex Lorenz   }
84*e82d89ccSAlex Lorenz 
85*e82d89ccSAlex Lorenz   raw_fd_ostream OS(FD, true);
86*e82d89ccSAlex Lorenz   OS << "llvmcovmtestdata";
87*e82d89ccSAlex Lorenz   encodeULEB128(ProfileNamesData.size(), OS);
88*e82d89ccSAlex Lorenz   encodeULEB128(ProfileNamesAddress, OS);
89*e82d89ccSAlex Lorenz   OS << ProfileNamesData << CoverageMappingData;
90*e82d89ccSAlex Lorenz 
91*e82d89ccSAlex Lorenz   return 0;
92*e82d89ccSAlex Lorenz }
93