1*9880d681SAndroid Build Coastguard Worker //===-- sancov.cc --------------------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file is a command-line tool for reading and analyzing sanitizer
11*9880d681SAndroid Build Coastguard Worker // coverage.
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/Symbolize/Symbolize.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstPrinter.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrAnalysis.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/Archive.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/Binary.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ELFObjectFile.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ObjectFile.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errc.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorOr.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LineIterator.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MD5.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/PrettyStackTrace.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Regex.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SpecialCaseList.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetSelect.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ToolOutputFile.h"
47*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker #include <algorithm>
50*9880d681SAndroid Build Coastguard Worker #include <set>
51*9880d681SAndroid Build Coastguard Worker #include <stdio.h>
52*9880d681SAndroid Build Coastguard Worker #include <string>
53*9880d681SAndroid Build Coastguard Worker #include <utility>
54*9880d681SAndroid Build Coastguard Worker #include <vector>
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker using namespace llvm;
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker namespace {
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker // --------- COMMAND LINE FLAGS ---------
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker enum ActionType {
63*9880d681SAndroid Build Coastguard Worker PrintAction,
64*9880d681SAndroid Build Coastguard Worker PrintCovPointsAction,
65*9880d681SAndroid Build Coastguard Worker CoveredFunctionsAction,
66*9880d681SAndroid Build Coastguard Worker NotCoveredFunctionsAction,
67*9880d681SAndroid Build Coastguard Worker HtmlReportAction,
68*9880d681SAndroid Build Coastguard Worker StatsAction
69*9880d681SAndroid Build Coastguard Worker };
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker cl::opt<ActionType> Action(
72*9880d681SAndroid Build Coastguard Worker cl::desc("Action (required)"), cl::Required,
73*9880d681SAndroid Build Coastguard Worker cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"),
74*9880d681SAndroid Build Coastguard Worker clEnumValN(PrintCovPointsAction, "print-coverage-pcs",
75*9880d681SAndroid Build Coastguard Worker "Print coverage instrumentation points addresses."),
76*9880d681SAndroid Build Coastguard Worker clEnumValN(CoveredFunctionsAction, "covered-functions",
77*9880d681SAndroid Build Coastguard Worker "Print all covered funcions."),
78*9880d681SAndroid Build Coastguard Worker clEnumValN(NotCoveredFunctionsAction, "not-covered-functions",
79*9880d681SAndroid Build Coastguard Worker "Print all not covered funcions."),
80*9880d681SAndroid Build Coastguard Worker clEnumValN(HtmlReportAction, "html-report",
81*9880d681SAndroid Build Coastguard Worker "Print HTML coverage report."),
82*9880d681SAndroid Build Coastguard Worker clEnumValN(StatsAction, "print-coverage-stats",
83*9880d681SAndroid Build Coastguard Worker "Print coverage statistics."),
84*9880d681SAndroid Build Coastguard Worker clEnumValEnd));
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
87*9880d681SAndroid Build Coastguard Worker ClInputFiles(cl::Positional, cl::OneOrMore,
88*9880d681SAndroid Build Coastguard Worker cl::desc("(<binary file>|<.sancov file>)..."));
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> ClDemangle("demangle", cl::init(true),
91*9880d681SAndroid Build Coastguard Worker cl::desc("Print demangled function name."));
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> ClStripPathPrefix(
94*9880d681SAndroid Build Coastguard Worker "strip_path_prefix", cl::init(""),
95*9880d681SAndroid Build Coastguard Worker cl::desc("Strip this prefix from file paths in reports."));
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
98*9880d681SAndroid Build Coastguard Worker ClBlacklist("blacklist", cl::init(""),
99*9880d681SAndroid Build Coastguard Worker cl::desc("Blacklist file (sanitizer blacklist format)."));
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> ClUseDefaultBlacklist(
102*9880d681SAndroid Build Coastguard Worker "use_default_blacklist", cl::init(true), cl::Hidden,
103*9880d681SAndroid Build Coastguard Worker cl::desc("Controls if default blacklist should be used."));
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker static const char *const DefaultBlacklistStr = "fun:__sanitizer_.*\n"
106*9880d681SAndroid Build Coastguard Worker "src:/usr/include/.*\n"
107*9880d681SAndroid Build Coastguard Worker "src:.*/libc\\+\\+/.*\n";
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker // --------- FORMAT SPECIFICATION ---------
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker struct FileHeader {
112*9880d681SAndroid Build Coastguard Worker uint32_t Bitness;
113*9880d681SAndroid Build Coastguard Worker uint32_t Magic;
114*9880d681SAndroid Build Coastguard Worker };
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker static const uint32_t BinCoverageMagic = 0xC0BFFFFF;
117*9880d681SAndroid Build Coastguard Worker static const uint32_t Bitness32 = 0xFFFFFF32;
118*9880d681SAndroid Build Coastguard Worker static const uint32_t Bitness64 = 0xFFFFFF64;
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // --------- ERROR HANDLING ---------
121*9880d681SAndroid Build Coastguard Worker
Fail(const llvm::Twine & E)122*9880d681SAndroid Build Coastguard Worker static void Fail(const llvm::Twine &E) {
123*9880d681SAndroid Build Coastguard Worker errs() << "Error: " << E << "\n";
124*9880d681SAndroid Build Coastguard Worker exit(1);
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker
FailIfError(std::error_code Error)127*9880d681SAndroid Build Coastguard Worker static void FailIfError(std::error_code Error) {
128*9880d681SAndroid Build Coastguard Worker if (!Error)
129*9880d681SAndroid Build Coastguard Worker return;
130*9880d681SAndroid Build Coastguard Worker errs() << "Error: " << Error.message() << "(" << Error.value() << ")\n";
131*9880d681SAndroid Build Coastguard Worker exit(1);
132*9880d681SAndroid Build Coastguard Worker }
133*9880d681SAndroid Build Coastguard Worker
FailIfError(const ErrorOr<T> & E)134*9880d681SAndroid Build Coastguard Worker template <typename T> static void FailIfError(const ErrorOr<T> &E) {
135*9880d681SAndroid Build Coastguard Worker FailIfError(E.getError());
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker
FailIfError(Error Err)138*9880d681SAndroid Build Coastguard Worker static void FailIfError(Error Err) {
139*9880d681SAndroid Build Coastguard Worker if (Err) {
140*9880d681SAndroid Build Coastguard Worker logAllUnhandledErrors(std::move(Err), errs(), "Error: ");
141*9880d681SAndroid Build Coastguard Worker exit(1);
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker
FailIfError(Expected<T> & E)145*9880d681SAndroid Build Coastguard Worker template <typename T> static void FailIfError(Expected<T> &E) {
146*9880d681SAndroid Build Coastguard Worker FailIfError(E.takeError());
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
FailIfNotEmpty(const llvm::Twine & E)149*9880d681SAndroid Build Coastguard Worker static void FailIfNotEmpty(const llvm::Twine &E) {
150*9880d681SAndroid Build Coastguard Worker if (E.str().empty())
151*9880d681SAndroid Build Coastguard Worker return;
152*9880d681SAndroid Build Coastguard Worker Fail(E);
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker template <typename T>
FailIfEmpty(const std::unique_ptr<T> & Ptr,const std::string & Message)156*9880d681SAndroid Build Coastguard Worker static void FailIfEmpty(const std::unique_ptr<T> &Ptr,
157*9880d681SAndroid Build Coastguard Worker const std::string &Message) {
158*9880d681SAndroid Build Coastguard Worker if (Ptr.get())
159*9880d681SAndroid Build Coastguard Worker return;
160*9880d681SAndroid Build Coastguard Worker Fail(Message);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker // ---------
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker // Produces std::map<K, std::vector<E>> grouping input
166*9880d681SAndroid Build Coastguard Worker // elements by FuncTy result.
167*9880d681SAndroid Build Coastguard Worker template <class RangeTy, class FuncTy>
group_by(const RangeTy & R,FuncTy F)168*9880d681SAndroid Build Coastguard Worker static inline auto group_by(const RangeTy &R, FuncTy F)
169*9880d681SAndroid Build Coastguard Worker -> std::map<typename std::decay<decltype(F(*R.begin()))>::type,
170*9880d681SAndroid Build Coastguard Worker std::vector<typename std::decay<decltype(*R.begin())>::type>> {
171*9880d681SAndroid Build Coastguard Worker std::map<typename std::decay<decltype(F(*R.begin()))>::type,
172*9880d681SAndroid Build Coastguard Worker std::vector<typename std::decay<decltype(*R.begin())>::type>>
173*9880d681SAndroid Build Coastguard Worker Result;
174*9880d681SAndroid Build Coastguard Worker for (const auto &E : R) {
175*9880d681SAndroid Build Coastguard Worker Result[F(E)].push_back(E);
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker return Result;
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker template <typename T>
readInts(const char * Start,const char * End,std::set<uint64_t> * Ints)181*9880d681SAndroid Build Coastguard Worker static void readInts(const char *Start, const char *End,
182*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> *Ints) {
183*9880d681SAndroid Build Coastguard Worker const T *S = reinterpret_cast<const T *>(Start);
184*9880d681SAndroid Build Coastguard Worker const T *E = reinterpret_cast<const T *>(End);
185*9880d681SAndroid Build Coastguard Worker std::copy(S, E, std::inserter(*Ints, Ints->end()));
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker struct FileLoc {
operator <__anondb1c28880111::FileLoc189*9880d681SAndroid Build Coastguard Worker bool operator<(const FileLoc &RHS) const {
190*9880d681SAndroid Build Coastguard Worker return std::tie(FileName, Line) < std::tie(RHS.FileName, RHS.Line);
191*9880d681SAndroid Build Coastguard Worker }
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker std::string FileName;
194*9880d681SAndroid Build Coastguard Worker uint32_t Line;
195*9880d681SAndroid Build Coastguard Worker };
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Worker struct FileFn {
operator <__anondb1c28880111::FileFn198*9880d681SAndroid Build Coastguard Worker bool operator<(const FileFn &RHS) const {
199*9880d681SAndroid Build Coastguard Worker return std::tie(FileName, FunctionName) <
200*9880d681SAndroid Build Coastguard Worker std::tie(RHS.FileName, RHS.FunctionName);
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker std::string FileName;
204*9880d681SAndroid Build Coastguard Worker std::string FunctionName;
205*9880d681SAndroid Build Coastguard Worker };
206*9880d681SAndroid Build Coastguard Worker
207*9880d681SAndroid Build Coastguard Worker struct FnLoc {
operator <__anondb1c28880111::FnLoc208*9880d681SAndroid Build Coastguard Worker bool operator<(const FnLoc &RHS) const {
209*9880d681SAndroid Build Coastguard Worker return std::tie(Loc, FunctionName) < std::tie(RHS.Loc, RHS.FunctionName);
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker FileLoc Loc;
213*9880d681SAndroid Build Coastguard Worker std::string FunctionName;
214*9880d681SAndroid Build Coastguard Worker };
215*9880d681SAndroid Build Coastguard Worker
stripPathPrefix(std::string Path)216*9880d681SAndroid Build Coastguard Worker std::string stripPathPrefix(std::string Path) {
217*9880d681SAndroid Build Coastguard Worker if (ClStripPathPrefix.empty())
218*9880d681SAndroid Build Coastguard Worker return Path;
219*9880d681SAndroid Build Coastguard Worker size_t Pos = Path.find(ClStripPathPrefix);
220*9880d681SAndroid Build Coastguard Worker if (Pos == std::string::npos)
221*9880d681SAndroid Build Coastguard Worker return Path;
222*9880d681SAndroid Build Coastguard Worker return Path.substr(Pos + ClStripPathPrefix.size());
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
createSymbolizer()225*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<symbolize::LLVMSymbolizer> createSymbolizer() {
226*9880d681SAndroid Build Coastguard Worker symbolize::LLVMSymbolizer::Options SymbolizerOptions;
227*9880d681SAndroid Build Coastguard Worker SymbolizerOptions.Demangle = ClDemangle;
228*9880d681SAndroid Build Coastguard Worker SymbolizerOptions.UseSymbolTable = true;
229*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<symbolize::LLVMSymbolizer>(
230*9880d681SAndroid Build Coastguard Worker new symbolize::LLVMSymbolizer(SymbolizerOptions));
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker
233*9880d681SAndroid Build Coastguard Worker // A DILineInfo with address.
234*9880d681SAndroid Build Coastguard Worker struct AddrInfo : public DILineInfo {
235*9880d681SAndroid Build Coastguard Worker uint64_t Addr;
236*9880d681SAndroid Build Coastguard Worker
AddrInfo__anondb1c28880111::AddrInfo237*9880d681SAndroid Build Coastguard Worker AddrInfo(const DILineInfo &DI, uint64_t Addr) : DILineInfo(DI), Addr(Addr) {
238*9880d681SAndroid Build Coastguard Worker FileName = normalizeFilename(FileName);
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker
241*9880d681SAndroid Build Coastguard Worker private:
normalizeFilename__anondb1c28880111::AddrInfo242*9880d681SAndroid Build Coastguard Worker static std::string normalizeFilename(const std::string &FileName) {
243*9880d681SAndroid Build Coastguard Worker SmallString<256> S(FileName);
244*9880d681SAndroid Build Coastguard Worker sys::path::remove_dots(S, /* remove_dot_dot */ true);
245*9880d681SAndroid Build Coastguard Worker return S.str().str();
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker };
248*9880d681SAndroid Build Coastguard Worker
249*9880d681SAndroid Build Coastguard Worker class Blacklists {
250*9880d681SAndroid Build Coastguard Worker public:
Blacklists()251*9880d681SAndroid Build Coastguard Worker Blacklists()
252*9880d681SAndroid Build Coastguard Worker : DefaultBlacklist(createDefaultBlacklist()),
253*9880d681SAndroid Build Coastguard Worker UserBlacklist(createUserBlacklist()) {}
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker // AddrInfo contains normalized filename. It is important to check it rather
256*9880d681SAndroid Build Coastguard Worker // than DILineInfo.
isBlacklisted(const AddrInfo & AI)257*9880d681SAndroid Build Coastguard Worker bool isBlacklisted(const AddrInfo &AI) {
258*9880d681SAndroid Build Coastguard Worker if (DefaultBlacklist && DefaultBlacklist->inSection("fun", AI.FunctionName))
259*9880d681SAndroid Build Coastguard Worker return true;
260*9880d681SAndroid Build Coastguard Worker if (DefaultBlacklist && DefaultBlacklist->inSection("src", AI.FileName))
261*9880d681SAndroid Build Coastguard Worker return true;
262*9880d681SAndroid Build Coastguard Worker if (UserBlacklist && UserBlacklist->inSection("fun", AI.FunctionName))
263*9880d681SAndroid Build Coastguard Worker return true;
264*9880d681SAndroid Build Coastguard Worker if (UserBlacklist && UserBlacklist->inSection("src", AI.FileName))
265*9880d681SAndroid Build Coastguard Worker return true;
266*9880d681SAndroid Build Coastguard Worker return false;
267*9880d681SAndroid Build Coastguard Worker }
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker private:
createDefaultBlacklist()270*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<SpecialCaseList> createDefaultBlacklist() {
271*9880d681SAndroid Build Coastguard Worker if (!ClUseDefaultBlacklist)
272*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<SpecialCaseList>();
273*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> MB =
274*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getMemBuffer(DefaultBlacklistStr);
275*9880d681SAndroid Build Coastguard Worker std::string Error;
276*9880d681SAndroid Build Coastguard Worker auto Blacklist = SpecialCaseList::create(MB.get(), Error);
277*9880d681SAndroid Build Coastguard Worker FailIfNotEmpty(Error);
278*9880d681SAndroid Build Coastguard Worker return Blacklist;
279*9880d681SAndroid Build Coastguard Worker }
280*9880d681SAndroid Build Coastguard Worker
createUserBlacklist()281*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<SpecialCaseList> createUserBlacklist() {
282*9880d681SAndroid Build Coastguard Worker if (ClBlacklist.empty())
283*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<SpecialCaseList>();
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard Worker return SpecialCaseList::createOrDie({{ClBlacklist}});
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker std::unique_ptr<SpecialCaseList> DefaultBlacklist;
288*9880d681SAndroid Build Coastguard Worker std::unique_ptr<SpecialCaseList> UserBlacklist;
289*9880d681SAndroid Build Coastguard Worker };
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker // Collect all debug info for given addresses.
getAddrInfo(const std::string & ObjectFile,const std::set<uint64_t> & Addrs,bool InlinedCode)292*9880d681SAndroid Build Coastguard Worker static std::vector<AddrInfo> getAddrInfo(const std::string &ObjectFile,
293*9880d681SAndroid Build Coastguard Worker const std::set<uint64_t> &Addrs,
294*9880d681SAndroid Build Coastguard Worker bool InlinedCode) {
295*9880d681SAndroid Build Coastguard Worker std::vector<AddrInfo> Result;
296*9880d681SAndroid Build Coastguard Worker auto Symbolizer(createSymbolizer());
297*9880d681SAndroid Build Coastguard Worker Blacklists B;
298*9880d681SAndroid Build Coastguard Worker
299*9880d681SAndroid Build Coastguard Worker for (auto Addr : Addrs) {
300*9880d681SAndroid Build Coastguard Worker auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr);
301*9880d681SAndroid Build Coastguard Worker FailIfError(LineInfo);
302*9880d681SAndroid Build Coastguard Worker auto LineAddrInfo = AddrInfo(*LineInfo, Addr);
303*9880d681SAndroid Build Coastguard Worker if (B.isBlacklisted(LineAddrInfo))
304*9880d681SAndroid Build Coastguard Worker continue;
305*9880d681SAndroid Build Coastguard Worker Result.push_back(LineAddrInfo);
306*9880d681SAndroid Build Coastguard Worker if (InlinedCode) {
307*9880d681SAndroid Build Coastguard Worker auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr);
308*9880d681SAndroid Build Coastguard Worker FailIfError(InliningInfo);
309*9880d681SAndroid Build Coastguard Worker for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) {
310*9880d681SAndroid Build Coastguard Worker auto FrameInfo = InliningInfo->getFrame(I);
311*9880d681SAndroid Build Coastguard Worker auto FrameAddrInfo = AddrInfo(FrameInfo, Addr);
312*9880d681SAndroid Build Coastguard Worker if (B.isBlacklisted(FrameAddrInfo))
313*9880d681SAndroid Build Coastguard Worker continue;
314*9880d681SAndroid Build Coastguard Worker Result.push_back(FrameAddrInfo);
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker }
317*9880d681SAndroid Build Coastguard Worker }
318*9880d681SAndroid Build Coastguard Worker
319*9880d681SAndroid Build Coastguard Worker return Result;
320*9880d681SAndroid Build Coastguard Worker }
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Worker // Locate __sanitizer_cov* function addresses that are used for coverage
323*9880d681SAndroid Build Coastguard Worker // reporting.
324*9880d681SAndroid Build Coastguard Worker static std::set<uint64_t>
findSanitizerCovFunctions(const object::ObjectFile & O)325*9880d681SAndroid Build Coastguard Worker findSanitizerCovFunctions(const object::ObjectFile &O) {
326*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> Result;
327*9880d681SAndroid Build Coastguard Worker
328*9880d681SAndroid Build Coastguard Worker for (const object::SymbolRef &Symbol : O.symbols()) {
329*9880d681SAndroid Build Coastguard Worker Expected<uint64_t> AddressOrErr = Symbol.getAddress();
330*9880d681SAndroid Build Coastguard Worker FailIfError(errorToErrorCode(AddressOrErr.takeError()));
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker Expected<StringRef> NameOrErr = Symbol.getName();
333*9880d681SAndroid Build Coastguard Worker FailIfError(errorToErrorCode(NameOrErr.takeError()));
334*9880d681SAndroid Build Coastguard Worker StringRef Name = NameOrErr.get();
335*9880d681SAndroid Build Coastguard Worker
336*9880d681SAndroid Build Coastguard Worker if (Name == "__sanitizer_cov" || Name == "__sanitizer_cov_with_check" ||
337*9880d681SAndroid Build Coastguard Worker Name == "__sanitizer_cov_trace_func_enter") {
338*9880d681SAndroid Build Coastguard Worker if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined))
339*9880d681SAndroid Build Coastguard Worker Result.insert(AddressOrErr.get());
340*9880d681SAndroid Build Coastguard Worker }
341*9880d681SAndroid Build Coastguard Worker }
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker return Result;
344*9880d681SAndroid Build Coastguard Worker }
345*9880d681SAndroid Build Coastguard Worker
346*9880d681SAndroid Build Coastguard Worker // Locate addresses of all coverage points in a file. Coverage point
347*9880d681SAndroid Build Coastguard Worker // is defined as the 'address of instruction following __sanitizer_cov
348*9880d681SAndroid Build Coastguard Worker // call - 1'.
getObjectCoveragePoints(const object::ObjectFile & O,std::set<uint64_t> * Addrs)349*9880d681SAndroid Build Coastguard Worker static void getObjectCoveragePoints(const object::ObjectFile &O,
350*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> *Addrs) {
351*9880d681SAndroid Build Coastguard Worker Triple TheTriple("unknown-unknown-unknown");
352*9880d681SAndroid Build Coastguard Worker TheTriple.setArch(Triple::ArchType(O.getArch()));
353*9880d681SAndroid Build Coastguard Worker auto TripleName = TheTriple.getTriple();
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard Worker std::string Error;
356*9880d681SAndroid Build Coastguard Worker const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
357*9880d681SAndroid Build Coastguard Worker FailIfNotEmpty(Error);
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCSubtargetInfo> STI(
360*9880d681SAndroid Build Coastguard Worker TheTarget->createMCSubtargetInfo(TripleName, "", ""));
361*9880d681SAndroid Build Coastguard Worker FailIfEmpty(STI, "no subtarget info for target " + TripleName);
362*9880d681SAndroid Build Coastguard Worker
363*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCRegisterInfo> MRI(
364*9880d681SAndroid Build Coastguard Worker TheTarget->createMCRegInfo(TripleName));
365*9880d681SAndroid Build Coastguard Worker FailIfEmpty(MRI, "no register info for target " + TripleName);
366*9880d681SAndroid Build Coastguard Worker
367*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCAsmInfo> AsmInfo(
368*9880d681SAndroid Build Coastguard Worker TheTarget->createMCAsmInfo(*MRI, TripleName));
369*9880d681SAndroid Build Coastguard Worker FailIfEmpty(AsmInfo, "no asm info for target " + TripleName);
370*9880d681SAndroid Build Coastguard Worker
371*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
372*9880d681SAndroid Build Coastguard Worker MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
373*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MCDisassembler> DisAsm(
374*9880d681SAndroid Build Coastguard Worker TheTarget->createMCDisassembler(*STI, Ctx));
375*9880d681SAndroid Build Coastguard Worker FailIfEmpty(DisAsm, "no disassembler info for target " + TripleName);
376*9880d681SAndroid Build Coastguard Worker
377*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
378*9880d681SAndroid Build Coastguard Worker FailIfEmpty(MII, "no instruction info for target " + TripleName);
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard Worker std::unique_ptr<const MCInstrAnalysis> MIA(
381*9880d681SAndroid Build Coastguard Worker TheTarget->createMCInstrAnalysis(MII.get()));
382*9880d681SAndroid Build Coastguard Worker FailIfEmpty(MIA, "no instruction analysis info for target " + TripleName);
383*9880d681SAndroid Build Coastguard Worker
384*9880d681SAndroid Build Coastguard Worker auto SanCovAddrs = findSanitizerCovFunctions(O);
385*9880d681SAndroid Build Coastguard Worker if (SanCovAddrs.empty())
386*9880d681SAndroid Build Coastguard Worker Fail("__sanitizer_cov* functions not found");
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker for (object::SectionRef Section : O.sections()) {
389*9880d681SAndroid Build Coastguard Worker if (Section.isVirtual() || !Section.isText()) // llvm-objdump does the same.
390*9880d681SAndroid Build Coastguard Worker continue;
391*9880d681SAndroid Build Coastguard Worker uint64_t SectionAddr = Section.getAddress();
392*9880d681SAndroid Build Coastguard Worker uint64_t SectSize = Section.getSize();
393*9880d681SAndroid Build Coastguard Worker if (!SectSize)
394*9880d681SAndroid Build Coastguard Worker continue;
395*9880d681SAndroid Build Coastguard Worker
396*9880d681SAndroid Build Coastguard Worker StringRef BytesStr;
397*9880d681SAndroid Build Coastguard Worker FailIfError(Section.getContents(BytesStr));
398*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
399*9880d681SAndroid Build Coastguard Worker BytesStr.size());
400*9880d681SAndroid Build Coastguard Worker
401*9880d681SAndroid Build Coastguard Worker for (uint64_t Index = 0, Size = 0; Index < Section.getSize();
402*9880d681SAndroid Build Coastguard Worker Index += Size) {
403*9880d681SAndroid Build Coastguard Worker MCInst Inst;
404*9880d681SAndroid Build Coastguard Worker if (!DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
405*9880d681SAndroid Build Coastguard Worker SectionAddr + Index, nulls(), nulls())) {
406*9880d681SAndroid Build Coastguard Worker if (Size == 0)
407*9880d681SAndroid Build Coastguard Worker Size = 1;
408*9880d681SAndroid Build Coastguard Worker continue;
409*9880d681SAndroid Build Coastguard Worker }
410*9880d681SAndroid Build Coastguard Worker uint64_t Addr = Index + SectionAddr;
411*9880d681SAndroid Build Coastguard Worker // Sanitizer coverage uses the address of the next instruction - 1.
412*9880d681SAndroid Build Coastguard Worker uint64_t CovPoint = Addr + Size - 1;
413*9880d681SAndroid Build Coastguard Worker uint64_t Target;
414*9880d681SAndroid Build Coastguard Worker if (MIA->isCall(Inst) &&
415*9880d681SAndroid Build Coastguard Worker MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target) &&
416*9880d681SAndroid Build Coastguard Worker SanCovAddrs.find(Target) != SanCovAddrs.end())
417*9880d681SAndroid Build Coastguard Worker Addrs->insert(CovPoint);
418*9880d681SAndroid Build Coastguard Worker }
419*9880d681SAndroid Build Coastguard Worker }
420*9880d681SAndroid Build Coastguard Worker }
421*9880d681SAndroid Build Coastguard Worker
422*9880d681SAndroid Build Coastguard Worker static void
visitObjectFiles(const object::Archive & A,function_ref<void (const object::ObjectFile &)> Fn)423*9880d681SAndroid Build Coastguard Worker visitObjectFiles(const object::Archive &A,
424*9880d681SAndroid Build Coastguard Worker function_ref<void(const object::ObjectFile &)> Fn) {
425*9880d681SAndroid Build Coastguard Worker Error Err;
426*9880d681SAndroid Build Coastguard Worker for (auto &C : A.children(Err)) {
427*9880d681SAndroid Build Coastguard Worker Expected<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary();
428*9880d681SAndroid Build Coastguard Worker FailIfError(errorToErrorCode(ChildOrErr.takeError()));
429*9880d681SAndroid Build Coastguard Worker if (auto *O = dyn_cast<object::ObjectFile>(&*ChildOrErr.get()))
430*9880d681SAndroid Build Coastguard Worker Fn(*O);
431*9880d681SAndroid Build Coastguard Worker else
432*9880d681SAndroid Build Coastguard Worker FailIfError(object::object_error::invalid_file_type);
433*9880d681SAndroid Build Coastguard Worker }
434*9880d681SAndroid Build Coastguard Worker FailIfError(std::move(Err));
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker static void
visitObjectFiles(const std::string & FileName,function_ref<void (const object::ObjectFile &)> Fn)438*9880d681SAndroid Build Coastguard Worker visitObjectFiles(const std::string &FileName,
439*9880d681SAndroid Build Coastguard Worker function_ref<void(const object::ObjectFile &)> Fn) {
440*9880d681SAndroid Build Coastguard Worker Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
441*9880d681SAndroid Build Coastguard Worker object::createBinary(FileName);
442*9880d681SAndroid Build Coastguard Worker if (!BinaryOrErr)
443*9880d681SAndroid Build Coastguard Worker FailIfError(errorToErrorCode(BinaryOrErr.takeError()));
444*9880d681SAndroid Build Coastguard Worker
445*9880d681SAndroid Build Coastguard Worker object::Binary &Binary = *BinaryOrErr.get().getBinary();
446*9880d681SAndroid Build Coastguard Worker if (object::Archive *A = dyn_cast<object::Archive>(&Binary))
447*9880d681SAndroid Build Coastguard Worker visitObjectFiles(*A, Fn);
448*9880d681SAndroid Build Coastguard Worker else if (object::ObjectFile *O = dyn_cast<object::ObjectFile>(&Binary))
449*9880d681SAndroid Build Coastguard Worker Fn(*O);
450*9880d681SAndroid Build Coastguard Worker else
451*9880d681SAndroid Build Coastguard Worker FailIfError(object::object_error::invalid_file_type);
452*9880d681SAndroid Build Coastguard Worker }
453*9880d681SAndroid Build Coastguard Worker
findSanitizerCovFunctions(const std::string & FileName)454*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> findSanitizerCovFunctions(const std::string &FileName) {
455*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> Result;
456*9880d681SAndroid Build Coastguard Worker visitObjectFiles(FileName, [&](const object::ObjectFile &O) {
457*9880d681SAndroid Build Coastguard Worker auto Addrs = findSanitizerCovFunctions(O);
458*9880d681SAndroid Build Coastguard Worker Result.insert(Addrs.begin(), Addrs.end());
459*9880d681SAndroid Build Coastguard Worker });
460*9880d681SAndroid Build Coastguard Worker return Result;
461*9880d681SAndroid Build Coastguard Worker }
462*9880d681SAndroid Build Coastguard Worker
463*9880d681SAndroid Build Coastguard Worker // Locate addresses of all coverage points in a file. Coverage point
464*9880d681SAndroid Build Coastguard Worker // is defined as the 'address of instruction following __sanitizer_cov
465*9880d681SAndroid Build Coastguard Worker // call - 1'.
getCoveragePoints(const std::string & FileName)466*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> getCoveragePoints(const std::string &FileName) {
467*9880d681SAndroid Build Coastguard Worker std::set<uint64_t> Result;
468*9880d681SAndroid Build Coastguard Worker visitObjectFiles(FileName, [&](const object::ObjectFile &O) {
469*9880d681SAndroid Build Coastguard Worker getObjectCoveragePoints(O, &Result);
470*9880d681SAndroid Build Coastguard Worker });
471*9880d681SAndroid Build Coastguard Worker return Result;
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker
printCovPoints(const std::string & ObjFile,raw_ostream & OS)474*9880d681SAndroid Build Coastguard Worker static void printCovPoints(const std::string &ObjFile, raw_ostream &OS) {
475*9880d681SAndroid Build Coastguard Worker for (uint64_t Addr : getCoveragePoints(ObjFile)) {
476*9880d681SAndroid Build Coastguard Worker OS << "0x";
477*9880d681SAndroid Build Coastguard Worker OS.write_hex(Addr);
478*9880d681SAndroid Build Coastguard Worker OS << "\n";
479*9880d681SAndroid Build Coastguard Worker }
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker
escapeHtml(const std::string & S)482*9880d681SAndroid Build Coastguard Worker static std::string escapeHtml(const std::string &S) {
483*9880d681SAndroid Build Coastguard Worker std::string Result;
484*9880d681SAndroid Build Coastguard Worker Result.reserve(S.size());
485*9880d681SAndroid Build Coastguard Worker for (char Ch : S) {
486*9880d681SAndroid Build Coastguard Worker switch (Ch) {
487*9880d681SAndroid Build Coastguard Worker case '&':
488*9880d681SAndroid Build Coastguard Worker Result.append("&");
489*9880d681SAndroid Build Coastguard Worker break;
490*9880d681SAndroid Build Coastguard Worker case '\'':
491*9880d681SAndroid Build Coastguard Worker Result.append("'");
492*9880d681SAndroid Build Coastguard Worker break;
493*9880d681SAndroid Build Coastguard Worker case '"':
494*9880d681SAndroid Build Coastguard Worker Result.append(""");
495*9880d681SAndroid Build Coastguard Worker break;
496*9880d681SAndroid Build Coastguard Worker case '<':
497*9880d681SAndroid Build Coastguard Worker Result.append("<");
498*9880d681SAndroid Build Coastguard Worker break;
499*9880d681SAndroid Build Coastguard Worker case '>':
500*9880d681SAndroid Build Coastguard Worker Result.append(">");
501*9880d681SAndroid Build Coastguard Worker break;
502*9880d681SAndroid Build Coastguard Worker default:
503*9880d681SAndroid Build Coastguard Worker Result.push_back(Ch);
504*9880d681SAndroid Build Coastguard Worker break;
505*9880d681SAndroid Build Coastguard Worker }
506*9880d681SAndroid Build Coastguard Worker }
507*9880d681SAndroid Build Coastguard Worker return Result;
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker
510*9880d681SAndroid Build Coastguard Worker // Adds leading zeroes wrapped in 'lz' style.
511*9880d681SAndroid Build Coastguard Worker // Leading zeroes help locate 000% coverage.
formatHtmlPct(size_t Pct)512*9880d681SAndroid Build Coastguard Worker static std::string formatHtmlPct(size_t Pct) {
513*9880d681SAndroid Build Coastguard Worker Pct = std::max(std::size_t{0}, std::min(std::size_t{100}, Pct));
514*9880d681SAndroid Build Coastguard Worker
515*9880d681SAndroid Build Coastguard Worker std::string Num = std::to_string(Pct);
516*9880d681SAndroid Build Coastguard Worker std::string Zeroes(3 - Num.size(), '0');
517*9880d681SAndroid Build Coastguard Worker if (!Zeroes.empty())
518*9880d681SAndroid Build Coastguard Worker Zeroes = "<span class='lz'>" + Zeroes + "</span>";
519*9880d681SAndroid Build Coastguard Worker
520*9880d681SAndroid Build Coastguard Worker return Zeroes + Num;
521*9880d681SAndroid Build Coastguard Worker }
522*9880d681SAndroid Build Coastguard Worker
anchorName(const std::string & Anchor)523*9880d681SAndroid Build Coastguard Worker static std::string anchorName(const std::string &Anchor) {
524*9880d681SAndroid Build Coastguard Worker llvm::MD5 Hasher;
525*9880d681SAndroid Build Coastguard Worker llvm::MD5::MD5Result Hash;
526*9880d681SAndroid Build Coastguard Worker Hasher.update(Anchor);
527*9880d681SAndroid Build Coastguard Worker Hasher.final(Hash);
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker SmallString<32> HexString;
530*9880d681SAndroid Build Coastguard Worker llvm::MD5::stringifyResult(Hash, HexString);
531*9880d681SAndroid Build Coastguard Worker return HexString.str().str();
532*9880d681SAndroid Build Coastguard Worker }
533*9880d681SAndroid Build Coastguard Worker
isCoverageFile(const std::string & FileName)534*9880d681SAndroid Build Coastguard Worker static ErrorOr<bool> isCoverageFile(const std::string &FileName) {
535*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
536*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFile(FileName);
537*9880d681SAndroid Build Coastguard Worker if (!BufOrErr) {
538*9880d681SAndroid Build Coastguard Worker errs() << "Warning: " << BufOrErr.getError().message() << "("
539*9880d681SAndroid Build Coastguard Worker << BufOrErr.getError().value()
540*9880d681SAndroid Build Coastguard Worker << "), filename: " << llvm::sys::path::filename(FileName) << "\n";
541*9880d681SAndroid Build Coastguard Worker return BufOrErr.getError();
542*9880d681SAndroid Build Coastguard Worker }
543*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
544*9880d681SAndroid Build Coastguard Worker if (Buf->getBufferSize() < 8) {
545*9880d681SAndroid Build Coastguard Worker return false;
546*9880d681SAndroid Build Coastguard Worker }
547*9880d681SAndroid Build Coastguard Worker const FileHeader *Header =
548*9880d681SAndroid Build Coastguard Worker reinterpret_cast<const FileHeader *>(Buf->getBufferStart());
549*9880d681SAndroid Build Coastguard Worker return Header->Magic == BinCoverageMagic;
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker
552*9880d681SAndroid Build Coastguard Worker struct CoverageStats {
CoverageStats__anondb1c28880111::CoverageStats553*9880d681SAndroid Build Coastguard Worker CoverageStats() : AllPoints(0), CovPoints(0), AllFns(0), CovFns(0) {}
554*9880d681SAndroid Build Coastguard Worker
555*9880d681SAndroid Build Coastguard Worker size_t AllPoints;
556*9880d681SAndroid Build Coastguard Worker size_t CovPoints;
557*9880d681SAndroid Build Coastguard Worker size_t AllFns;
558*9880d681SAndroid Build Coastguard Worker size_t CovFns;
559*9880d681SAndroid Build Coastguard Worker };
560*9880d681SAndroid Build Coastguard Worker
operator <<(raw_ostream & OS,const CoverageStats & Stats)561*9880d681SAndroid Build Coastguard Worker static raw_ostream &operator<<(raw_ostream &OS, const CoverageStats &Stats) {
562*9880d681SAndroid Build Coastguard Worker OS << "all-edges: " << Stats.AllPoints << "\n";
563*9880d681SAndroid Build Coastguard Worker OS << "cov-edges: " << Stats.CovPoints << "\n";
564*9880d681SAndroid Build Coastguard Worker OS << "all-functions: " << Stats.AllFns << "\n";
565*9880d681SAndroid Build Coastguard Worker OS << "cov-functions: " << Stats.CovFns << "\n";
566*9880d681SAndroid Build Coastguard Worker return OS;
567*9880d681SAndroid Build Coastguard Worker }
568*9880d681SAndroid Build Coastguard Worker
569*9880d681SAndroid Build Coastguard Worker class CoverageData {
570*9880d681SAndroid Build Coastguard Worker public:
571*9880d681SAndroid Build Coastguard Worker // Read single file coverage data.
572*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<CoverageData>>
read(const std::string & FileName)573*9880d681SAndroid Build Coastguard Worker read(const std::string &FileName) {
574*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
575*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFile(FileName);
576*9880d681SAndroid Build Coastguard Worker if (!BufOrErr)
577*9880d681SAndroid Build Coastguard Worker return BufOrErr.getError();
578*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
579*9880d681SAndroid Build Coastguard Worker if (Buf->getBufferSize() < 8) {
580*9880d681SAndroid Build Coastguard Worker errs() << "File too small (<8): " << Buf->getBufferSize();
581*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::illegal_byte_sequence);
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker const FileHeader *Header =
584*9880d681SAndroid Build Coastguard Worker reinterpret_cast<const FileHeader *>(Buf->getBufferStart());
585*9880d681SAndroid Build Coastguard Worker
586*9880d681SAndroid Build Coastguard Worker if (Header->Magic != BinCoverageMagic) {
587*9880d681SAndroid Build Coastguard Worker errs() << "Wrong magic: " << Header->Magic;
588*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::illegal_byte_sequence);
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker
591*9880d681SAndroid Build Coastguard Worker auto Addrs = llvm::make_unique<std::set<uint64_t>>();
592*9880d681SAndroid Build Coastguard Worker
593*9880d681SAndroid Build Coastguard Worker switch (Header->Bitness) {
594*9880d681SAndroid Build Coastguard Worker case Bitness64:
595*9880d681SAndroid Build Coastguard Worker readInts<uint64_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),
596*9880d681SAndroid Build Coastguard Worker Addrs.get());
597*9880d681SAndroid Build Coastguard Worker break;
598*9880d681SAndroid Build Coastguard Worker case Bitness32:
599*9880d681SAndroid Build Coastguard Worker readInts<uint32_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),
600*9880d681SAndroid Build Coastguard Worker Addrs.get());
601*9880d681SAndroid Build Coastguard Worker break;
602*9880d681SAndroid Build Coastguard Worker default:
603*9880d681SAndroid Build Coastguard Worker errs() << "Unsupported bitness: " << Header->Bitness;
604*9880d681SAndroid Build Coastguard Worker return make_error_code(errc::illegal_byte_sequence);
605*9880d681SAndroid Build Coastguard Worker }
606*9880d681SAndroid Build Coastguard Worker
607*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));
608*9880d681SAndroid Build Coastguard Worker }
609*9880d681SAndroid Build Coastguard Worker
610*9880d681SAndroid Build Coastguard Worker // Merge multiple coverage data together.
611*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<CoverageData>
merge(const std::vector<std::unique_ptr<CoverageData>> & Covs)612*9880d681SAndroid Build Coastguard Worker merge(const std::vector<std::unique_ptr<CoverageData>> &Covs) {
613*9880d681SAndroid Build Coastguard Worker auto Addrs = llvm::make_unique<std::set<uint64_t>>();
614*9880d681SAndroid Build Coastguard Worker
615*9880d681SAndroid Build Coastguard Worker for (const auto &Cov : Covs)
616*9880d681SAndroid Build Coastguard Worker Addrs->insert(Cov->Addrs->begin(), Cov->Addrs->end());
617*9880d681SAndroid Build Coastguard Worker
618*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));
619*9880d681SAndroid Build Coastguard Worker }
620*9880d681SAndroid Build Coastguard Worker
621*9880d681SAndroid Build Coastguard Worker // Read list of files and merges their coverage info.
622*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<CoverageData>>
readAndMerge(const std::vector<std::string> & FileNames)623*9880d681SAndroid Build Coastguard Worker readAndMerge(const std::vector<std::string> &FileNames) {
624*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<CoverageData>> Covs;
625*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : FileNames) {
626*9880d681SAndroid Build Coastguard Worker auto Cov = read(FileName);
627*9880d681SAndroid Build Coastguard Worker if (!Cov)
628*9880d681SAndroid Build Coastguard Worker return Cov.getError();
629*9880d681SAndroid Build Coastguard Worker Covs.push_back(std::move(Cov.get()));
630*9880d681SAndroid Build Coastguard Worker }
631*9880d681SAndroid Build Coastguard Worker return merge(Covs);
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
634*9880d681SAndroid Build Coastguard Worker // Print coverage addresses.
printAddrs(raw_ostream & OS)635*9880d681SAndroid Build Coastguard Worker void printAddrs(raw_ostream &OS) {
636*9880d681SAndroid Build Coastguard Worker for (auto Addr : *Addrs) {
637*9880d681SAndroid Build Coastguard Worker OS << "0x";
638*9880d681SAndroid Build Coastguard Worker OS.write_hex(Addr);
639*9880d681SAndroid Build Coastguard Worker OS << "\n";
640*9880d681SAndroid Build Coastguard Worker }
641*9880d681SAndroid Build Coastguard Worker }
642*9880d681SAndroid Build Coastguard Worker
643*9880d681SAndroid Build Coastguard Worker protected:
CoverageData(std::unique_ptr<std::set<uint64_t>> Addrs)644*9880d681SAndroid Build Coastguard Worker explicit CoverageData(std::unique_ptr<std::set<uint64_t>> Addrs)
645*9880d681SAndroid Build Coastguard Worker : Addrs(std::move(Addrs)) {}
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker friend class CoverageDataWithObjectFile;
648*9880d681SAndroid Build Coastguard Worker
649*9880d681SAndroid Build Coastguard Worker std::unique_ptr<std::set<uint64_t>> Addrs;
650*9880d681SAndroid Build Coastguard Worker };
651*9880d681SAndroid Build Coastguard Worker
652*9880d681SAndroid Build Coastguard Worker // Coverage data translated into source code line-level information.
653*9880d681SAndroid Build Coastguard Worker // Fetches debug info in constructor and calculates various information per
654*9880d681SAndroid Build Coastguard Worker // request.
655*9880d681SAndroid Build Coastguard Worker class SourceCoverageData {
656*9880d681SAndroid Build Coastguard Worker public:
657*9880d681SAndroid Build Coastguard Worker enum LineStatus {
658*9880d681SAndroid Build Coastguard Worker // coverage information for the line is not available.
659*9880d681SAndroid Build Coastguard Worker // default value in maps.
660*9880d681SAndroid Build Coastguard Worker UNKNOWN = 0,
661*9880d681SAndroid Build Coastguard Worker // the line is fully covered.
662*9880d681SAndroid Build Coastguard Worker COVERED = 1,
663*9880d681SAndroid Build Coastguard Worker // the line is fully uncovered.
664*9880d681SAndroid Build Coastguard Worker NOT_COVERED = 2,
665*9880d681SAndroid Build Coastguard Worker // some points in the line a covered, some are not.
666*9880d681SAndroid Build Coastguard Worker MIXED = 3
667*9880d681SAndroid Build Coastguard Worker };
668*9880d681SAndroid Build Coastguard Worker
SourceCoverageData(std::string ObjectFile,const std::set<uint64_t> & Addrs)669*9880d681SAndroid Build Coastguard Worker SourceCoverageData(std::string ObjectFile, const std::set<uint64_t> &Addrs)
670*9880d681SAndroid Build Coastguard Worker : AllCovPoints(getCoveragePoints(ObjectFile)) {
671*9880d681SAndroid Build Coastguard Worker if (!std::includes(AllCovPoints.begin(), AllCovPoints.end(), Addrs.begin(),
672*9880d681SAndroid Build Coastguard Worker Addrs.end())) {
673*9880d681SAndroid Build Coastguard Worker Fail("Coverage points in binary and .sancov file do not match.");
674*9880d681SAndroid Build Coastguard Worker }
675*9880d681SAndroid Build Coastguard Worker
676*9880d681SAndroid Build Coastguard Worker AllAddrInfo = getAddrInfo(ObjectFile, AllCovPoints, true);
677*9880d681SAndroid Build Coastguard Worker CovAddrInfo = getAddrInfo(ObjectFile, Addrs, true);
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker
680*9880d681SAndroid Build Coastguard Worker // Compute number of coverage points hit/total in a file.
681*9880d681SAndroid Build Coastguard Worker // file_name -> <coverage, all_coverage>
computeFileCoverage()682*9880d681SAndroid Build Coastguard Worker std::map<std::string, std::pair<size_t, size_t>> computeFileCoverage() {
683*9880d681SAndroid Build Coastguard Worker std::map<std::string, std::pair<size_t, size_t>> FileCoverage;
684*9880d681SAndroid Build Coastguard Worker auto AllCovPointsByFile =
685*9880d681SAndroid Build Coastguard Worker group_by(AllAddrInfo, [](const AddrInfo &AI) { return AI.FileName; });
686*9880d681SAndroid Build Coastguard Worker auto CovPointsByFile =
687*9880d681SAndroid Build Coastguard Worker group_by(CovAddrInfo, [](const AddrInfo &AI) { return AI.FileName; });
688*9880d681SAndroid Build Coastguard Worker
689*9880d681SAndroid Build Coastguard Worker for (const auto &P : AllCovPointsByFile) {
690*9880d681SAndroid Build Coastguard Worker const std::string &FileName = P.first;
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker FileCoverage[FileName] =
693*9880d681SAndroid Build Coastguard Worker std::make_pair(CovPointsByFile[FileName].size(),
694*9880d681SAndroid Build Coastguard Worker AllCovPointsByFile[FileName].size());
695*9880d681SAndroid Build Coastguard Worker }
696*9880d681SAndroid Build Coastguard Worker return FileCoverage;
697*9880d681SAndroid Build Coastguard Worker }
698*9880d681SAndroid Build Coastguard Worker
699*9880d681SAndroid Build Coastguard Worker // line_number -> line_status.
700*9880d681SAndroid Build Coastguard Worker typedef std::map<int, LineStatus> LineStatusMap;
701*9880d681SAndroid Build Coastguard Worker // file_name -> LineStatusMap
702*9880d681SAndroid Build Coastguard Worker typedef std::map<std::string, LineStatusMap> FileLineStatusMap;
703*9880d681SAndroid Build Coastguard Worker
704*9880d681SAndroid Build Coastguard Worker // fills in the {file_name -> {line_no -> status}} map.
computeLineStatusMap()705*9880d681SAndroid Build Coastguard Worker FileLineStatusMap computeLineStatusMap() {
706*9880d681SAndroid Build Coastguard Worker FileLineStatusMap StatusMap;
707*9880d681SAndroid Build Coastguard Worker
708*9880d681SAndroid Build Coastguard Worker auto AllLocs = group_by(AllAddrInfo, [](const AddrInfo &AI) {
709*9880d681SAndroid Build Coastguard Worker return FileLoc{AI.FileName, AI.Line};
710*9880d681SAndroid Build Coastguard Worker });
711*9880d681SAndroid Build Coastguard Worker auto CovLocs = group_by(CovAddrInfo, [](const AddrInfo &AI) {
712*9880d681SAndroid Build Coastguard Worker return FileLoc{AI.FileName, AI.Line};
713*9880d681SAndroid Build Coastguard Worker });
714*9880d681SAndroid Build Coastguard Worker
715*9880d681SAndroid Build Coastguard Worker for (const auto &P : AllLocs) {
716*9880d681SAndroid Build Coastguard Worker const FileLoc &Loc = P.first;
717*9880d681SAndroid Build Coastguard Worker auto I = CovLocs.find(Loc);
718*9880d681SAndroid Build Coastguard Worker
719*9880d681SAndroid Build Coastguard Worker if (I == CovLocs.end()) {
720*9880d681SAndroid Build Coastguard Worker StatusMap[Loc.FileName][Loc.Line] = NOT_COVERED;
721*9880d681SAndroid Build Coastguard Worker } else {
722*9880d681SAndroid Build Coastguard Worker StatusMap[Loc.FileName][Loc.Line] =
723*9880d681SAndroid Build Coastguard Worker (I->second.size() == P.second.size()) ? COVERED : MIXED;
724*9880d681SAndroid Build Coastguard Worker }
725*9880d681SAndroid Build Coastguard Worker }
726*9880d681SAndroid Build Coastguard Worker return StatusMap;
727*9880d681SAndroid Build Coastguard Worker }
728*9880d681SAndroid Build Coastguard Worker
computeAllFunctions() const729*9880d681SAndroid Build Coastguard Worker std::set<FileFn> computeAllFunctions() const {
730*9880d681SAndroid Build Coastguard Worker std::set<FileFn> Fns;
731*9880d681SAndroid Build Coastguard Worker for (const auto &AI : AllAddrInfo) {
732*9880d681SAndroid Build Coastguard Worker Fns.insert(FileFn{AI.FileName, AI.FunctionName});
733*9880d681SAndroid Build Coastguard Worker }
734*9880d681SAndroid Build Coastguard Worker return Fns;
735*9880d681SAndroid Build Coastguard Worker }
736*9880d681SAndroid Build Coastguard Worker
computeCoveredFunctions() const737*9880d681SAndroid Build Coastguard Worker std::set<FileFn> computeCoveredFunctions() const {
738*9880d681SAndroid Build Coastguard Worker std::set<FileFn> Fns;
739*9880d681SAndroid Build Coastguard Worker auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {
740*9880d681SAndroid Build Coastguard Worker return FileFn{AI.FileName, AI.FunctionName};
741*9880d681SAndroid Build Coastguard Worker });
742*9880d681SAndroid Build Coastguard Worker
743*9880d681SAndroid Build Coastguard Worker for (const auto &P : CovFns) {
744*9880d681SAndroid Build Coastguard Worker Fns.insert(P.first);
745*9880d681SAndroid Build Coastguard Worker }
746*9880d681SAndroid Build Coastguard Worker return Fns;
747*9880d681SAndroid Build Coastguard Worker }
748*9880d681SAndroid Build Coastguard Worker
computeNotCoveredFunctions() const749*9880d681SAndroid Build Coastguard Worker std::set<FileFn> computeNotCoveredFunctions() const {
750*9880d681SAndroid Build Coastguard Worker std::set<FileFn> Fns;
751*9880d681SAndroid Build Coastguard Worker
752*9880d681SAndroid Build Coastguard Worker auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) {
753*9880d681SAndroid Build Coastguard Worker return FileFn{AI.FileName, AI.FunctionName};
754*9880d681SAndroid Build Coastguard Worker });
755*9880d681SAndroid Build Coastguard Worker auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {
756*9880d681SAndroid Build Coastguard Worker return FileFn{AI.FileName, AI.FunctionName};
757*9880d681SAndroid Build Coastguard Worker });
758*9880d681SAndroid Build Coastguard Worker
759*9880d681SAndroid Build Coastguard Worker for (const auto &P : AllFns) {
760*9880d681SAndroid Build Coastguard Worker if (CovFns.find(P.first) == CovFns.end()) {
761*9880d681SAndroid Build Coastguard Worker Fns.insert(P.first);
762*9880d681SAndroid Build Coastguard Worker }
763*9880d681SAndroid Build Coastguard Worker }
764*9880d681SAndroid Build Coastguard Worker return Fns;
765*9880d681SAndroid Build Coastguard Worker }
766*9880d681SAndroid Build Coastguard Worker
767*9880d681SAndroid Build Coastguard Worker // Compute % coverage for each function.
computeFunctionsCoverage() const768*9880d681SAndroid Build Coastguard Worker std::map<FileFn, int> computeFunctionsCoverage() const {
769*9880d681SAndroid Build Coastguard Worker std::map<FileFn, int> FnCoverage;
770*9880d681SAndroid Build Coastguard Worker auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) {
771*9880d681SAndroid Build Coastguard Worker return FileFn{AI.FileName, AI.FunctionName};
772*9880d681SAndroid Build Coastguard Worker });
773*9880d681SAndroid Build Coastguard Worker
774*9880d681SAndroid Build Coastguard Worker auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {
775*9880d681SAndroid Build Coastguard Worker return FileFn{AI.FileName, AI.FunctionName};
776*9880d681SAndroid Build Coastguard Worker });
777*9880d681SAndroid Build Coastguard Worker
778*9880d681SAndroid Build Coastguard Worker for (const auto &P : AllFns) {
779*9880d681SAndroid Build Coastguard Worker FileFn F = P.first;
780*9880d681SAndroid Build Coastguard Worker FnCoverage[F] = CovFns[F].size() * 100 / P.second.size();
781*9880d681SAndroid Build Coastguard Worker }
782*9880d681SAndroid Build Coastguard Worker
783*9880d681SAndroid Build Coastguard Worker return FnCoverage;
784*9880d681SAndroid Build Coastguard Worker }
785*9880d681SAndroid Build Coastguard Worker
786*9880d681SAndroid Build Coastguard Worker typedef std::map<FileLoc, std::set<std::string>> FunctionLocs;
787*9880d681SAndroid Build Coastguard Worker // finds first line number in a file for each function.
resolveFunctions(const std::set<FileFn> & Fns) const788*9880d681SAndroid Build Coastguard Worker FunctionLocs resolveFunctions(const std::set<FileFn> &Fns) const {
789*9880d681SAndroid Build Coastguard Worker std::vector<AddrInfo> FnAddrs;
790*9880d681SAndroid Build Coastguard Worker for (const auto &AI : AllAddrInfo) {
791*9880d681SAndroid Build Coastguard Worker if (Fns.find(FileFn{AI.FileName, AI.FunctionName}) != Fns.end())
792*9880d681SAndroid Build Coastguard Worker FnAddrs.push_back(AI);
793*9880d681SAndroid Build Coastguard Worker }
794*9880d681SAndroid Build Coastguard Worker
795*9880d681SAndroid Build Coastguard Worker auto GroupedAddrs = group_by(FnAddrs, [](const AddrInfo &AI) {
796*9880d681SAndroid Build Coastguard Worker return FnLoc{FileLoc{AI.FileName, AI.Line}, AI.FunctionName};
797*9880d681SAndroid Build Coastguard Worker });
798*9880d681SAndroid Build Coastguard Worker
799*9880d681SAndroid Build Coastguard Worker FunctionLocs Result;
800*9880d681SAndroid Build Coastguard Worker std::string LastFileName;
801*9880d681SAndroid Build Coastguard Worker std::set<std::string> ProcessedFunctions;
802*9880d681SAndroid Build Coastguard Worker
803*9880d681SAndroid Build Coastguard Worker for (const auto &P : GroupedAddrs) {
804*9880d681SAndroid Build Coastguard Worker const FnLoc &Loc = P.first;
805*9880d681SAndroid Build Coastguard Worker std::string FileName = Loc.Loc.FileName;
806*9880d681SAndroid Build Coastguard Worker std::string FunctionName = Loc.FunctionName;
807*9880d681SAndroid Build Coastguard Worker
808*9880d681SAndroid Build Coastguard Worker if (LastFileName != FileName)
809*9880d681SAndroid Build Coastguard Worker ProcessedFunctions.clear();
810*9880d681SAndroid Build Coastguard Worker LastFileName = FileName;
811*9880d681SAndroid Build Coastguard Worker
812*9880d681SAndroid Build Coastguard Worker if (!ProcessedFunctions.insert(FunctionName).second)
813*9880d681SAndroid Build Coastguard Worker continue;
814*9880d681SAndroid Build Coastguard Worker
815*9880d681SAndroid Build Coastguard Worker auto FLoc = FileLoc{FileName, Loc.Loc.Line};
816*9880d681SAndroid Build Coastguard Worker Result[FLoc].insert(FunctionName);
817*9880d681SAndroid Build Coastguard Worker }
818*9880d681SAndroid Build Coastguard Worker return Result;
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker
files() const821*9880d681SAndroid Build Coastguard Worker std::set<std::string> files() const {
822*9880d681SAndroid Build Coastguard Worker std::set<std::string> Files;
823*9880d681SAndroid Build Coastguard Worker for (const auto &AI : AllAddrInfo) {
824*9880d681SAndroid Build Coastguard Worker Files.insert(AI.FileName);
825*9880d681SAndroid Build Coastguard Worker }
826*9880d681SAndroid Build Coastguard Worker return Files;
827*9880d681SAndroid Build Coastguard Worker }
828*9880d681SAndroid Build Coastguard Worker
collectStats(CoverageStats * Stats) const829*9880d681SAndroid Build Coastguard Worker void collectStats(CoverageStats *Stats) const {
830*9880d681SAndroid Build Coastguard Worker Stats->AllPoints += AllCovPoints.size();
831*9880d681SAndroid Build Coastguard Worker Stats->AllFns += computeAllFunctions().size();
832*9880d681SAndroid Build Coastguard Worker Stats->CovFns += computeCoveredFunctions().size();
833*9880d681SAndroid Build Coastguard Worker }
834*9880d681SAndroid Build Coastguard Worker
835*9880d681SAndroid Build Coastguard Worker private:
836*9880d681SAndroid Build Coastguard Worker const std::set<uint64_t> AllCovPoints;
837*9880d681SAndroid Build Coastguard Worker
838*9880d681SAndroid Build Coastguard Worker std::vector<AddrInfo> AllAddrInfo;
839*9880d681SAndroid Build Coastguard Worker std::vector<AddrInfo> CovAddrInfo;
840*9880d681SAndroid Build Coastguard Worker };
841*9880d681SAndroid Build Coastguard Worker
printFunctionLocs(const SourceCoverageData::FunctionLocs & FnLocs,raw_ostream & OS)842*9880d681SAndroid Build Coastguard Worker static void printFunctionLocs(const SourceCoverageData::FunctionLocs &FnLocs,
843*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) {
844*9880d681SAndroid Build Coastguard Worker for (const auto &Fns : FnLocs) {
845*9880d681SAndroid Build Coastguard Worker for (const auto &Fn : Fns.second) {
846*9880d681SAndroid Build Coastguard Worker OS << stripPathPrefix(Fns.first.FileName) << ":" << Fns.first.Line << " "
847*9880d681SAndroid Build Coastguard Worker << Fn << "\n";
848*9880d681SAndroid Build Coastguard Worker }
849*9880d681SAndroid Build Coastguard Worker }
850*9880d681SAndroid Build Coastguard Worker }
851*9880d681SAndroid Build Coastguard Worker
852*9880d681SAndroid Build Coastguard Worker // Holder for coverage data + filename of corresponding object file.
853*9880d681SAndroid Build Coastguard Worker class CoverageDataWithObjectFile : public CoverageData {
854*9880d681SAndroid Build Coastguard Worker public:
855*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<CoverageDataWithObjectFile>>
readAndMerge(const std::string & ObjectFile,const std::vector<std::string> & FileNames)856*9880d681SAndroid Build Coastguard Worker readAndMerge(const std::string &ObjectFile,
857*9880d681SAndroid Build Coastguard Worker const std::vector<std::string> &FileNames) {
858*9880d681SAndroid Build Coastguard Worker auto MergedDataOrError = CoverageData::readAndMerge(FileNames);
859*9880d681SAndroid Build Coastguard Worker if (!MergedDataOrError)
860*9880d681SAndroid Build Coastguard Worker return MergedDataOrError.getError();
861*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<CoverageDataWithObjectFile>(
862*9880d681SAndroid Build Coastguard Worker new CoverageDataWithObjectFile(ObjectFile,
863*9880d681SAndroid Build Coastguard Worker std::move(MergedDataOrError.get())));
864*9880d681SAndroid Build Coastguard Worker }
865*9880d681SAndroid Build Coastguard Worker
object_file() const866*9880d681SAndroid Build Coastguard Worker std::string object_file() const { return ObjectFile; }
867*9880d681SAndroid Build Coastguard Worker
868*9880d681SAndroid Build Coastguard Worker // Print list of covered functions.
869*9880d681SAndroid Build Coastguard Worker // Line format: <file_name>:<line> <function_name>
printCoveredFunctions(raw_ostream & OS) const870*9880d681SAndroid Build Coastguard Worker void printCoveredFunctions(raw_ostream &OS) const {
871*9880d681SAndroid Build Coastguard Worker SourceCoverageData SCovData(ObjectFile, *Addrs);
872*9880d681SAndroid Build Coastguard Worker auto CoveredFns = SCovData.computeCoveredFunctions();
873*9880d681SAndroid Build Coastguard Worker printFunctionLocs(SCovData.resolveFunctions(CoveredFns), OS);
874*9880d681SAndroid Build Coastguard Worker }
875*9880d681SAndroid Build Coastguard Worker
876*9880d681SAndroid Build Coastguard Worker // Print list of not covered functions.
877*9880d681SAndroid Build Coastguard Worker // Line format: <file_name>:<line> <function_name>
printNotCoveredFunctions(raw_ostream & OS) const878*9880d681SAndroid Build Coastguard Worker void printNotCoveredFunctions(raw_ostream &OS) const {
879*9880d681SAndroid Build Coastguard Worker SourceCoverageData SCovData(ObjectFile, *Addrs);
880*9880d681SAndroid Build Coastguard Worker auto NotCoveredFns = SCovData.computeNotCoveredFunctions();
881*9880d681SAndroid Build Coastguard Worker printFunctionLocs(SCovData.resolveFunctions(NotCoveredFns), OS);
882*9880d681SAndroid Build Coastguard Worker }
883*9880d681SAndroid Build Coastguard Worker
printReport(raw_ostream & OS) const884*9880d681SAndroid Build Coastguard Worker void printReport(raw_ostream &OS) const {
885*9880d681SAndroid Build Coastguard Worker SourceCoverageData SCovData(ObjectFile, *Addrs);
886*9880d681SAndroid Build Coastguard Worker auto LineStatusMap = SCovData.computeLineStatusMap();
887*9880d681SAndroid Build Coastguard Worker
888*9880d681SAndroid Build Coastguard Worker std::set<FileFn> AllFns = SCovData.computeAllFunctions();
889*9880d681SAndroid Build Coastguard Worker // file_loc -> set[function_name]
890*9880d681SAndroid Build Coastguard Worker auto AllFnsByLoc = SCovData.resolveFunctions(AllFns);
891*9880d681SAndroid Build Coastguard Worker auto FileCoverage = SCovData.computeFileCoverage();
892*9880d681SAndroid Build Coastguard Worker
893*9880d681SAndroid Build Coastguard Worker auto FnCoverage = SCovData.computeFunctionsCoverage();
894*9880d681SAndroid Build Coastguard Worker auto FnCoverageByFile =
895*9880d681SAndroid Build Coastguard Worker group_by(FnCoverage, [](const std::pair<FileFn, int> &FileFn) {
896*9880d681SAndroid Build Coastguard Worker return FileFn.first.FileName;
897*9880d681SAndroid Build Coastguard Worker });
898*9880d681SAndroid Build Coastguard Worker
899*9880d681SAndroid Build Coastguard Worker // TOC
900*9880d681SAndroid Build Coastguard Worker
901*9880d681SAndroid Build Coastguard Worker size_t NotCoveredFilesCount = 0;
902*9880d681SAndroid Build Coastguard Worker std::set<std::string> Files = SCovData.files();
903*9880d681SAndroid Build Coastguard Worker
904*9880d681SAndroid Build Coastguard Worker // Covered Files.
905*9880d681SAndroid Build Coastguard Worker OS << "<details open><summary>Touched Files</summary>\n";
906*9880d681SAndroid Build Coastguard Worker OS << "<table>\n";
907*9880d681SAndroid Build Coastguard Worker OS << "<tr><th>File</th><th>Coverage %</th>";
908*9880d681SAndroid Build Coastguard Worker OS << "<th>Hit (Total) Fns</th></tr>\n";
909*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : Files) {
910*9880d681SAndroid Build Coastguard Worker std::pair<size_t, size_t> FC = FileCoverage[FileName];
911*9880d681SAndroid Build Coastguard Worker if (FC.first == 0) {
912*9880d681SAndroid Build Coastguard Worker NotCoveredFilesCount++;
913*9880d681SAndroid Build Coastguard Worker continue;
914*9880d681SAndroid Build Coastguard Worker }
915*9880d681SAndroid Build Coastguard Worker size_t CovPct = FC.second == 0 ? 100 : 100 * FC.first / FC.second;
916*9880d681SAndroid Build Coastguard Worker
917*9880d681SAndroid Build Coastguard Worker OS << "<tr><td><a href=\"#" << anchorName(FileName) << "\">"
918*9880d681SAndroid Build Coastguard Worker << stripPathPrefix(FileName) << "</a></td>"
919*9880d681SAndroid Build Coastguard Worker << "<td>" << formatHtmlPct(CovPct) << "%</td>"
920*9880d681SAndroid Build Coastguard Worker << "<td>" << FC.first << " (" << FC.second << ")"
921*9880d681SAndroid Build Coastguard Worker << "</tr>\n";
922*9880d681SAndroid Build Coastguard Worker }
923*9880d681SAndroid Build Coastguard Worker OS << "</table>\n";
924*9880d681SAndroid Build Coastguard Worker OS << "</details>\n";
925*9880d681SAndroid Build Coastguard Worker
926*9880d681SAndroid Build Coastguard Worker // Not covered files.
927*9880d681SAndroid Build Coastguard Worker if (NotCoveredFilesCount) {
928*9880d681SAndroid Build Coastguard Worker OS << "<details><summary>Not Touched Files</summary>\n";
929*9880d681SAndroid Build Coastguard Worker OS << "<table>\n";
930*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : Files) {
931*9880d681SAndroid Build Coastguard Worker std::pair<size_t, size_t> FC = FileCoverage[FileName];
932*9880d681SAndroid Build Coastguard Worker if (FC.first == 0)
933*9880d681SAndroid Build Coastguard Worker OS << "<tr><td>" << stripPathPrefix(FileName) << "</td>\n";
934*9880d681SAndroid Build Coastguard Worker }
935*9880d681SAndroid Build Coastguard Worker OS << "</table>\n";
936*9880d681SAndroid Build Coastguard Worker OS << "</details>\n";
937*9880d681SAndroid Build Coastguard Worker } else {
938*9880d681SAndroid Build Coastguard Worker OS << "<p>Congratulations! All source files are touched.</p>\n";
939*9880d681SAndroid Build Coastguard Worker }
940*9880d681SAndroid Build Coastguard Worker
941*9880d681SAndroid Build Coastguard Worker // Source
942*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : Files) {
943*9880d681SAndroid Build Coastguard Worker std::pair<size_t, size_t> FC = FileCoverage[FileName];
944*9880d681SAndroid Build Coastguard Worker if (FC.first == 0)
945*9880d681SAndroid Build Coastguard Worker continue;
946*9880d681SAndroid Build Coastguard Worker OS << "<a name=\"" << anchorName(FileName) << "\"></a>\n";
947*9880d681SAndroid Build Coastguard Worker OS << "<h2>" << stripPathPrefix(FileName) << "</h2>\n";
948*9880d681SAndroid Build Coastguard Worker OS << "<details open><summary>Function Coverage</summary>";
949*9880d681SAndroid Build Coastguard Worker OS << "<div class='fnlist'>\n";
950*9880d681SAndroid Build Coastguard Worker
951*9880d681SAndroid Build Coastguard Worker auto &FileFnCoverage = FnCoverageByFile[FileName];
952*9880d681SAndroid Build Coastguard Worker
953*9880d681SAndroid Build Coastguard Worker for (const auto &P : FileFnCoverage) {
954*9880d681SAndroid Build Coastguard Worker std::string FunctionName = P.first.FunctionName;
955*9880d681SAndroid Build Coastguard Worker
956*9880d681SAndroid Build Coastguard Worker OS << "<div class='fn' style='order: " << P.second << "'>";
957*9880d681SAndroid Build Coastguard Worker OS << "<span class='pct'>" << formatHtmlPct(P.second)
958*9880d681SAndroid Build Coastguard Worker << "%</span> ";
959*9880d681SAndroid Build Coastguard Worker OS << "<span class='name'><a href=\"#"
960*9880d681SAndroid Build Coastguard Worker << anchorName(FileName + "::" + FunctionName) << "\">";
961*9880d681SAndroid Build Coastguard Worker OS << escapeHtml(FunctionName) << "</a></span>";
962*9880d681SAndroid Build Coastguard Worker OS << "</div>\n";
963*9880d681SAndroid Build Coastguard Worker }
964*9880d681SAndroid Build Coastguard Worker OS << "</div></details>\n";
965*9880d681SAndroid Build Coastguard Worker
966*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
967*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFile(FileName);
968*9880d681SAndroid Build Coastguard Worker if (!BufOrErr) {
969*9880d681SAndroid Build Coastguard Worker OS << "Error reading file: " << FileName << " : "
970*9880d681SAndroid Build Coastguard Worker << BufOrErr.getError().message() << "("
971*9880d681SAndroid Build Coastguard Worker << BufOrErr.getError().value() << ")\n";
972*9880d681SAndroid Build Coastguard Worker continue;
973*9880d681SAndroid Build Coastguard Worker }
974*9880d681SAndroid Build Coastguard Worker
975*9880d681SAndroid Build Coastguard Worker OS << "<pre>\n";
976*9880d681SAndroid Build Coastguard Worker const auto &LineStatuses = LineStatusMap[FileName];
977*9880d681SAndroid Build Coastguard Worker for (line_iterator I = line_iterator(*BufOrErr.get(), false);
978*9880d681SAndroid Build Coastguard Worker !I.is_at_eof(); ++I) {
979*9880d681SAndroid Build Coastguard Worker uint32_t Line = I.line_number();
980*9880d681SAndroid Build Coastguard Worker { // generate anchors (if any);
981*9880d681SAndroid Build Coastguard Worker FileLoc Loc = FileLoc{FileName, Line};
982*9880d681SAndroid Build Coastguard Worker auto It = AllFnsByLoc.find(Loc);
983*9880d681SAndroid Build Coastguard Worker if (It != AllFnsByLoc.end()) {
984*9880d681SAndroid Build Coastguard Worker for (const std::string &Fn : It->second) {
985*9880d681SAndroid Build Coastguard Worker OS << "<a name=\"" << anchorName(FileName + "::" + Fn)
986*9880d681SAndroid Build Coastguard Worker << "\"></a>";
987*9880d681SAndroid Build Coastguard Worker };
988*9880d681SAndroid Build Coastguard Worker }
989*9880d681SAndroid Build Coastguard Worker }
990*9880d681SAndroid Build Coastguard Worker
991*9880d681SAndroid Build Coastguard Worker OS << "<span ";
992*9880d681SAndroid Build Coastguard Worker auto LIT = LineStatuses.find(I.line_number());
993*9880d681SAndroid Build Coastguard Worker auto Status = (LIT != LineStatuses.end()) ? LIT->second
994*9880d681SAndroid Build Coastguard Worker : SourceCoverageData::UNKNOWN;
995*9880d681SAndroid Build Coastguard Worker switch (Status) {
996*9880d681SAndroid Build Coastguard Worker case SourceCoverageData::UNKNOWN:
997*9880d681SAndroid Build Coastguard Worker OS << "class=unknown";
998*9880d681SAndroid Build Coastguard Worker break;
999*9880d681SAndroid Build Coastguard Worker case SourceCoverageData::COVERED:
1000*9880d681SAndroid Build Coastguard Worker OS << "class=covered";
1001*9880d681SAndroid Build Coastguard Worker break;
1002*9880d681SAndroid Build Coastguard Worker case SourceCoverageData::NOT_COVERED:
1003*9880d681SAndroid Build Coastguard Worker OS << "class=notcovered";
1004*9880d681SAndroid Build Coastguard Worker break;
1005*9880d681SAndroid Build Coastguard Worker case SourceCoverageData::MIXED:
1006*9880d681SAndroid Build Coastguard Worker OS << "class=mixed";
1007*9880d681SAndroid Build Coastguard Worker break;
1008*9880d681SAndroid Build Coastguard Worker }
1009*9880d681SAndroid Build Coastguard Worker OS << ">";
1010*9880d681SAndroid Build Coastguard Worker OS << escapeHtml(*I) << "</span>\n";
1011*9880d681SAndroid Build Coastguard Worker }
1012*9880d681SAndroid Build Coastguard Worker OS << "</pre>\n";
1013*9880d681SAndroid Build Coastguard Worker }
1014*9880d681SAndroid Build Coastguard Worker }
1015*9880d681SAndroid Build Coastguard Worker
collectStats(CoverageStats * Stats) const1016*9880d681SAndroid Build Coastguard Worker void collectStats(CoverageStats *Stats) const {
1017*9880d681SAndroid Build Coastguard Worker Stats->CovPoints += Addrs->size();
1018*9880d681SAndroid Build Coastguard Worker
1019*9880d681SAndroid Build Coastguard Worker SourceCoverageData SCovData(ObjectFile, *Addrs);
1020*9880d681SAndroid Build Coastguard Worker SCovData.collectStats(Stats);
1021*9880d681SAndroid Build Coastguard Worker }
1022*9880d681SAndroid Build Coastguard Worker
1023*9880d681SAndroid Build Coastguard Worker private:
CoverageDataWithObjectFile(std::string ObjectFile,std::unique_ptr<CoverageData> Coverage)1024*9880d681SAndroid Build Coastguard Worker CoverageDataWithObjectFile(std::string ObjectFile,
1025*9880d681SAndroid Build Coastguard Worker std::unique_ptr<CoverageData> Coverage)
1026*9880d681SAndroid Build Coastguard Worker : CoverageData(std::move(Coverage->Addrs)),
1027*9880d681SAndroid Build Coastguard Worker ObjectFile(std::move(ObjectFile)) {}
1028*9880d681SAndroid Build Coastguard Worker const std::string ObjectFile;
1029*9880d681SAndroid Build Coastguard Worker };
1030*9880d681SAndroid Build Coastguard Worker
1031*9880d681SAndroid Build Coastguard Worker // Multiple coverage files data organized by object file.
1032*9880d681SAndroid Build Coastguard Worker class CoverageDataSet {
1033*9880d681SAndroid Build Coastguard Worker public:
1034*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<CoverageDataSet>>
readCmdArguments(std::vector<std::string> FileNames)1035*9880d681SAndroid Build Coastguard Worker readCmdArguments(std::vector<std::string> FileNames) {
1036*9880d681SAndroid Build Coastguard Worker // Short name => file name.
1037*9880d681SAndroid Build Coastguard Worker std::map<std::string, std::string> ObjFiles;
1038*9880d681SAndroid Build Coastguard Worker std::string FirstObjFile;
1039*9880d681SAndroid Build Coastguard Worker std::set<std::string> CovFiles;
1040*9880d681SAndroid Build Coastguard Worker
1041*9880d681SAndroid Build Coastguard Worker // Partition input values into coverage/object files.
1042*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : FileNames) {
1043*9880d681SAndroid Build Coastguard Worker auto ErrorOrIsCoverage = isCoverageFile(FileName);
1044*9880d681SAndroid Build Coastguard Worker if (!ErrorOrIsCoverage)
1045*9880d681SAndroid Build Coastguard Worker continue;
1046*9880d681SAndroid Build Coastguard Worker if (ErrorOrIsCoverage.get()) {
1047*9880d681SAndroid Build Coastguard Worker CovFiles.insert(FileName);
1048*9880d681SAndroid Build Coastguard Worker } else {
1049*9880d681SAndroid Build Coastguard Worker auto ShortFileName = llvm::sys::path::filename(FileName);
1050*9880d681SAndroid Build Coastguard Worker if (ObjFiles.find(ShortFileName) != ObjFiles.end()) {
1051*9880d681SAndroid Build Coastguard Worker Fail("Duplicate binary file with a short name: " + ShortFileName);
1052*9880d681SAndroid Build Coastguard Worker }
1053*9880d681SAndroid Build Coastguard Worker
1054*9880d681SAndroid Build Coastguard Worker ObjFiles[ShortFileName] = FileName;
1055*9880d681SAndroid Build Coastguard Worker if (FirstObjFile.empty())
1056*9880d681SAndroid Build Coastguard Worker FirstObjFile = FileName;
1057*9880d681SAndroid Build Coastguard Worker }
1058*9880d681SAndroid Build Coastguard Worker }
1059*9880d681SAndroid Build Coastguard Worker
1060*9880d681SAndroid Build Coastguard Worker Regex SancovRegex("(.*)\\.[0-9]+\\.sancov");
1061*9880d681SAndroid Build Coastguard Worker SmallVector<StringRef, 2> Components;
1062*9880d681SAndroid Build Coastguard Worker
1063*9880d681SAndroid Build Coastguard Worker // Object file => list of corresponding coverage file names.
1064*9880d681SAndroid Build Coastguard Worker auto CoverageByObjFile = group_by(CovFiles, [&](std::string FileName) {
1065*9880d681SAndroid Build Coastguard Worker auto ShortFileName = llvm::sys::path::filename(FileName);
1066*9880d681SAndroid Build Coastguard Worker auto Ok = SancovRegex.match(ShortFileName, &Components);
1067*9880d681SAndroid Build Coastguard Worker if (!Ok) {
1068*9880d681SAndroid Build Coastguard Worker Fail("Can't match coverage file name against "
1069*9880d681SAndroid Build Coastguard Worker "<module_name>.<pid>.sancov pattern: " +
1070*9880d681SAndroid Build Coastguard Worker FileName);
1071*9880d681SAndroid Build Coastguard Worker }
1072*9880d681SAndroid Build Coastguard Worker
1073*9880d681SAndroid Build Coastguard Worker auto Iter = ObjFiles.find(Components[1]);
1074*9880d681SAndroid Build Coastguard Worker if (Iter == ObjFiles.end()) {
1075*9880d681SAndroid Build Coastguard Worker Fail("Object file for coverage not found: " + FileName);
1076*9880d681SAndroid Build Coastguard Worker }
1077*9880d681SAndroid Build Coastguard Worker return Iter->second;
1078*9880d681SAndroid Build Coastguard Worker });
1079*9880d681SAndroid Build Coastguard Worker
1080*9880d681SAndroid Build Coastguard Worker // Read coverage.
1081*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<CoverageDataWithObjectFile>> MergedCoverage;
1082*9880d681SAndroid Build Coastguard Worker for (const auto &Pair : CoverageByObjFile) {
1083*9880d681SAndroid Build Coastguard Worker if (findSanitizerCovFunctions(Pair.first).empty()) {
1084*9880d681SAndroid Build Coastguard Worker for (const auto &FileName : Pair.second) {
1085*9880d681SAndroid Build Coastguard Worker CovFiles.erase(FileName);
1086*9880d681SAndroid Build Coastguard Worker }
1087*9880d681SAndroid Build Coastguard Worker
1088*9880d681SAndroid Build Coastguard Worker errs()
1089*9880d681SAndroid Build Coastguard Worker << "Ignoring " << Pair.first
1090*9880d681SAndroid Build Coastguard Worker << " and its coverage because __sanitizer_cov* functions were not "
1091*9880d681SAndroid Build Coastguard Worker "found.\n";
1092*9880d681SAndroid Build Coastguard Worker continue;
1093*9880d681SAndroid Build Coastguard Worker }
1094*9880d681SAndroid Build Coastguard Worker
1095*9880d681SAndroid Build Coastguard Worker auto DataOrError =
1096*9880d681SAndroid Build Coastguard Worker CoverageDataWithObjectFile::readAndMerge(Pair.first, Pair.second);
1097*9880d681SAndroid Build Coastguard Worker FailIfError(DataOrError);
1098*9880d681SAndroid Build Coastguard Worker MergedCoverage.push_back(std::move(DataOrError.get()));
1099*9880d681SAndroid Build Coastguard Worker }
1100*9880d681SAndroid Build Coastguard Worker
1101*9880d681SAndroid Build Coastguard Worker return std::unique_ptr<CoverageDataSet>(
1102*9880d681SAndroid Build Coastguard Worker new CoverageDataSet(FirstObjFile, &MergedCoverage, CovFiles));
1103*9880d681SAndroid Build Coastguard Worker }
1104*9880d681SAndroid Build Coastguard Worker
printCoveredFunctions(raw_ostream & OS) const1105*9880d681SAndroid Build Coastguard Worker void printCoveredFunctions(raw_ostream &OS) const {
1106*9880d681SAndroid Build Coastguard Worker for (const auto &Cov : Coverage) {
1107*9880d681SAndroid Build Coastguard Worker Cov->printCoveredFunctions(OS);
1108*9880d681SAndroid Build Coastguard Worker }
1109*9880d681SAndroid Build Coastguard Worker }
1110*9880d681SAndroid Build Coastguard Worker
printNotCoveredFunctions(raw_ostream & OS) const1111*9880d681SAndroid Build Coastguard Worker void printNotCoveredFunctions(raw_ostream &OS) const {
1112*9880d681SAndroid Build Coastguard Worker for (const auto &Cov : Coverage) {
1113*9880d681SAndroid Build Coastguard Worker Cov->printNotCoveredFunctions(OS);
1114*9880d681SAndroid Build Coastguard Worker }
1115*9880d681SAndroid Build Coastguard Worker }
1116*9880d681SAndroid Build Coastguard Worker
printStats(raw_ostream & OS) const1117*9880d681SAndroid Build Coastguard Worker void printStats(raw_ostream &OS) const {
1118*9880d681SAndroid Build Coastguard Worker CoverageStats Stats;
1119*9880d681SAndroid Build Coastguard Worker for (const auto &Cov : Coverage) {
1120*9880d681SAndroid Build Coastguard Worker Cov->collectStats(&Stats);
1121*9880d681SAndroid Build Coastguard Worker }
1122*9880d681SAndroid Build Coastguard Worker OS << Stats;
1123*9880d681SAndroid Build Coastguard Worker }
1124*9880d681SAndroid Build Coastguard Worker
printReport(raw_ostream & OS) const1125*9880d681SAndroid Build Coastguard Worker void printReport(raw_ostream &OS) const {
1126*9880d681SAndroid Build Coastguard Worker auto Title =
1127*9880d681SAndroid Build Coastguard Worker (llvm::sys::path::filename(MainObjFile) + " Coverage Report").str();
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker OS << "<html>\n";
1130*9880d681SAndroid Build Coastguard Worker OS << "<head>\n";
1131*9880d681SAndroid Build Coastguard Worker
1132*9880d681SAndroid Build Coastguard Worker // Stylesheet
1133*9880d681SAndroid Build Coastguard Worker OS << "<style>\n";
1134*9880d681SAndroid Build Coastguard Worker OS << ".covered { background: #7F7; }\n";
1135*9880d681SAndroid Build Coastguard Worker OS << ".notcovered { background: #F77; }\n";
1136*9880d681SAndroid Build Coastguard Worker OS << ".mixed { background: #FF7; }\n";
1137*9880d681SAndroid Build Coastguard Worker OS << "summary { font-weight: bold; }\n";
1138*9880d681SAndroid Build Coastguard Worker OS << "details > summary + * { margin-left: 1em; }\n";
1139*9880d681SAndroid Build Coastguard Worker OS << ".fnlist { display: flex; flex-flow: column nowrap; }\n";
1140*9880d681SAndroid Build Coastguard Worker OS << ".fn { display: flex; flex-flow: row nowrap; }\n";
1141*9880d681SAndroid Build Coastguard Worker OS << ".pct { width: 3em; text-align: right; margin-right: 1em; }\n";
1142*9880d681SAndroid Build Coastguard Worker OS << ".name { flex: 2; }\n";
1143*9880d681SAndroid Build Coastguard Worker OS << ".lz { color: lightgray; }\n";
1144*9880d681SAndroid Build Coastguard Worker OS << "</style>\n";
1145*9880d681SAndroid Build Coastguard Worker OS << "<title>" << Title << "</title>\n";
1146*9880d681SAndroid Build Coastguard Worker OS << "</head>\n";
1147*9880d681SAndroid Build Coastguard Worker OS << "<body>\n";
1148*9880d681SAndroid Build Coastguard Worker
1149*9880d681SAndroid Build Coastguard Worker // Title
1150*9880d681SAndroid Build Coastguard Worker OS << "<h1>" << Title << "</h1>\n";
1151*9880d681SAndroid Build Coastguard Worker
1152*9880d681SAndroid Build Coastguard Worker // Modules TOC.
1153*9880d681SAndroid Build Coastguard Worker if (Coverage.size() > 1) {
1154*9880d681SAndroid Build Coastguard Worker for (const auto &CovData : Coverage) {
1155*9880d681SAndroid Build Coastguard Worker OS << "<li><a href=\"#module_" << anchorName(CovData->object_file())
1156*9880d681SAndroid Build Coastguard Worker << "\">" << llvm::sys::path::filename(CovData->object_file())
1157*9880d681SAndroid Build Coastguard Worker << "</a></li>\n";
1158*9880d681SAndroid Build Coastguard Worker }
1159*9880d681SAndroid Build Coastguard Worker }
1160*9880d681SAndroid Build Coastguard Worker
1161*9880d681SAndroid Build Coastguard Worker for (const auto &CovData : Coverage) {
1162*9880d681SAndroid Build Coastguard Worker if (Coverage.size() > 1) {
1163*9880d681SAndroid Build Coastguard Worker OS << "<h2>" << llvm::sys::path::filename(CovData->object_file())
1164*9880d681SAndroid Build Coastguard Worker << "</h2>\n";
1165*9880d681SAndroid Build Coastguard Worker }
1166*9880d681SAndroid Build Coastguard Worker OS << "<a name=\"module_" << anchorName(CovData->object_file())
1167*9880d681SAndroid Build Coastguard Worker << "\"></a>\n";
1168*9880d681SAndroid Build Coastguard Worker CovData->printReport(OS);
1169*9880d681SAndroid Build Coastguard Worker }
1170*9880d681SAndroid Build Coastguard Worker
1171*9880d681SAndroid Build Coastguard Worker // About
1172*9880d681SAndroid Build Coastguard Worker OS << "<details><summary>About</summary>\n";
1173*9880d681SAndroid Build Coastguard Worker OS << "Coverage files:<ul>";
1174*9880d681SAndroid Build Coastguard Worker for (const auto &InputFile : CoverageFiles) {
1175*9880d681SAndroid Build Coastguard Worker llvm::sys::fs::file_status Status;
1176*9880d681SAndroid Build Coastguard Worker llvm::sys::fs::status(InputFile, Status);
1177*9880d681SAndroid Build Coastguard Worker OS << "<li>" << stripPathPrefix(InputFile) << " ("
1178*9880d681SAndroid Build Coastguard Worker << Status.getLastModificationTime().str() << ")</li>\n";
1179*9880d681SAndroid Build Coastguard Worker }
1180*9880d681SAndroid Build Coastguard Worker OS << "</ul></details>\n";
1181*9880d681SAndroid Build Coastguard Worker
1182*9880d681SAndroid Build Coastguard Worker OS << "</body>\n";
1183*9880d681SAndroid Build Coastguard Worker OS << "</html>\n";
1184*9880d681SAndroid Build Coastguard Worker }
1185*9880d681SAndroid Build Coastguard Worker
empty() const1186*9880d681SAndroid Build Coastguard Worker bool empty() const { return Coverage.empty(); }
1187*9880d681SAndroid Build Coastguard Worker
1188*9880d681SAndroid Build Coastguard Worker private:
CoverageDataSet(const std::string & MainObjFile,std::vector<std::unique_ptr<CoverageDataWithObjectFile>> * Data,const std::set<std::string> & CoverageFiles)1189*9880d681SAndroid Build Coastguard Worker explicit CoverageDataSet(
1190*9880d681SAndroid Build Coastguard Worker const std::string &MainObjFile,
1191*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<CoverageDataWithObjectFile>> *Data,
1192*9880d681SAndroid Build Coastguard Worker const std::set<std::string> &CoverageFiles)
1193*9880d681SAndroid Build Coastguard Worker : MainObjFile(MainObjFile), CoverageFiles(CoverageFiles) {
1194*9880d681SAndroid Build Coastguard Worker Data->swap(this->Coverage);
1195*9880d681SAndroid Build Coastguard Worker }
1196*9880d681SAndroid Build Coastguard Worker
1197*9880d681SAndroid Build Coastguard Worker const std::string MainObjFile;
1198*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<CoverageDataWithObjectFile>> Coverage;
1199*9880d681SAndroid Build Coastguard Worker const std::set<std::string> CoverageFiles;
1200*9880d681SAndroid Build Coastguard Worker };
1201*9880d681SAndroid Build Coastguard Worker
1202*9880d681SAndroid Build Coastguard Worker } // namespace
1203*9880d681SAndroid Build Coastguard Worker
main(int argc,char ** argv)1204*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
1205*9880d681SAndroid Build Coastguard Worker // Print stack trace if we signal out.
1206*9880d681SAndroid Build Coastguard Worker sys::PrintStackTraceOnErrorSignal(argv[0]);
1207*9880d681SAndroid Build Coastguard Worker PrettyStackTraceProgram X(argc, argv);
1208*9880d681SAndroid Build Coastguard Worker llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
1209*9880d681SAndroid Build Coastguard Worker
1210*9880d681SAndroid Build Coastguard Worker llvm::InitializeAllTargetInfos();
1211*9880d681SAndroid Build Coastguard Worker llvm::InitializeAllTargetMCs();
1212*9880d681SAndroid Build Coastguard Worker llvm::InitializeAllDisassemblers();
1213*9880d681SAndroid Build Coastguard Worker
1214*9880d681SAndroid Build Coastguard Worker cl::ParseCommandLineOptions(argc, argv, "Sanitizer Coverage Processing Tool");
1215*9880d681SAndroid Build Coastguard Worker
1216*9880d681SAndroid Build Coastguard Worker // -print doesn't need object files.
1217*9880d681SAndroid Build Coastguard Worker if (Action == PrintAction) {
1218*9880d681SAndroid Build Coastguard Worker auto CovData = CoverageData::readAndMerge(ClInputFiles);
1219*9880d681SAndroid Build Coastguard Worker FailIfError(CovData);
1220*9880d681SAndroid Build Coastguard Worker CovData.get()->printAddrs(outs());
1221*9880d681SAndroid Build Coastguard Worker return 0;
1222*9880d681SAndroid Build Coastguard Worker } else if (Action == PrintCovPointsAction) {
1223*9880d681SAndroid Build Coastguard Worker // -print-coverage-points doesn't need coverage files.
1224*9880d681SAndroid Build Coastguard Worker for (const std::string &ObjFile : ClInputFiles) {
1225*9880d681SAndroid Build Coastguard Worker printCovPoints(ObjFile, outs());
1226*9880d681SAndroid Build Coastguard Worker }
1227*9880d681SAndroid Build Coastguard Worker return 0;
1228*9880d681SAndroid Build Coastguard Worker }
1229*9880d681SAndroid Build Coastguard Worker
1230*9880d681SAndroid Build Coastguard Worker auto CovDataSet = CoverageDataSet::readCmdArguments(ClInputFiles);
1231*9880d681SAndroid Build Coastguard Worker FailIfError(CovDataSet);
1232*9880d681SAndroid Build Coastguard Worker
1233*9880d681SAndroid Build Coastguard Worker if (CovDataSet.get()->empty()) {
1234*9880d681SAndroid Build Coastguard Worker Fail("No coverage files specified.");
1235*9880d681SAndroid Build Coastguard Worker }
1236*9880d681SAndroid Build Coastguard Worker
1237*9880d681SAndroid Build Coastguard Worker switch (Action) {
1238*9880d681SAndroid Build Coastguard Worker case CoveredFunctionsAction: {
1239*9880d681SAndroid Build Coastguard Worker CovDataSet.get()->printCoveredFunctions(outs());
1240*9880d681SAndroid Build Coastguard Worker return 0;
1241*9880d681SAndroid Build Coastguard Worker }
1242*9880d681SAndroid Build Coastguard Worker case NotCoveredFunctionsAction: {
1243*9880d681SAndroid Build Coastguard Worker CovDataSet.get()->printNotCoveredFunctions(outs());
1244*9880d681SAndroid Build Coastguard Worker return 0;
1245*9880d681SAndroid Build Coastguard Worker }
1246*9880d681SAndroid Build Coastguard Worker case HtmlReportAction: {
1247*9880d681SAndroid Build Coastguard Worker CovDataSet.get()->printReport(outs());
1248*9880d681SAndroid Build Coastguard Worker return 0;
1249*9880d681SAndroid Build Coastguard Worker }
1250*9880d681SAndroid Build Coastguard Worker case StatsAction: {
1251*9880d681SAndroid Build Coastguard Worker CovDataSet.get()->printStats(outs());
1252*9880d681SAndroid Build Coastguard Worker return 0;
1253*9880d681SAndroid Build Coastguard Worker }
1254*9880d681SAndroid Build Coastguard Worker case PrintAction:
1255*9880d681SAndroid Build Coastguard Worker case PrintCovPointsAction:
1256*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported action");
1257*9880d681SAndroid Build Coastguard Worker }
1258*9880d681SAndroid Build Coastguard Worker }
1259