94d8c4c7aabdc0c9d1ee0ec78f0f8b40678f6998
[oota-llvm.git] / tools / sancov / sancov.cc
1 //===-- sancov.cc --------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a command-line tool for reading and analyzing sanitizer
11 // coverage.
12 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
15 #include "llvm/MC/MCAsmInfo.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCDisassembler.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstPrinter.h"
20 #include "llvm/MC/MCInstrAnalysis.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCObjectFileInfo.h"
23 #include "llvm/MC/MCRegisterInfo.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/Object/Binary.h"
26 #include "llvm/Object/ObjectFile.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Errc.h"
29 #include "llvm/Support/ErrorOr.h"
30 #include "llvm/Support/FileSystem.h"
31 #include "llvm/Support/LineIterator.h"
32 #include "llvm/Support/ManagedStatic.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/Path.h"
35 #include "llvm/Support/PrettyStackTrace.h"
36 #include "llvm/Support/Signals.h"
37 #include "llvm/Support/TargetRegistry.h"
38 #include "llvm/Support/TargetSelect.h"
39 #include "llvm/Support/ToolOutputFile.h"
40 #include "llvm/Support/raw_ostream.h"
41
42 #include <set>
43 #include <stdio.h>
44 #include <string>
45 #include <vector>
46
47 using namespace llvm;
48
49 namespace {
50
51 // --------- COMMAND LINE FLAGS ---------
52
53 enum ActionType {
54   PrintAction,
55   CoveredFunctionsAction,
56   NotCoveredFunctionsAction
57 };
58
59 cl::opt<ActionType> Action(
60     cl::desc("Action (required)"), cl::Required,
61     cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"),
62                clEnumValN(CoveredFunctionsAction, "covered-functions",
63                           "Print all covered funcions."),
64                clEnumValN(NotCoveredFunctionsAction, "not-covered-functions",
65                           "Print all not covered funcions."),
66                clEnumValEnd));
67
68 static cl::list<std::string> ClInputFiles(cl::Positional, cl::OneOrMore,
69                                           cl::desc("<filenames...>"));
70
71 static cl::opt<std::string>
72     ClBinaryName("obj", cl::Required,
73                  cl::desc("Path to object file to be symbolized"));
74
75 static cl::opt<bool>
76     ClDemangle("demangle", cl::init(true),
77         cl::desc("Print demangled function name."));
78
79 static cl::opt<std::string> ClStripPathPrefix(
80     "strip_path_prefix", cl::init(""),
81     cl::desc("Strip this prefix from file paths in reports."));
82
83 // --------- FORMAT SPECIFICATION ---------
84
85 struct FileHeader {
86   uint32_t Bitness;
87   uint32_t Magic;
88 };
89
90 static const uint32_t BinCoverageMagic = 0xC0BFFFFF;
91 static const uint32_t Bitness32 = 0xFFFFFF32;
92 static const uint32_t Bitness64 = 0xFFFFFF64;
93
94 // ---------
95
96 static void FailIfError(std::error_code Error) {
97   if (!Error)
98     return;
99   errs() << "Error: " << Error.message() << "(" << Error.value() << ")\n";
100   exit(1);
101 }
102
103 template <typename T> static void FailIfError(const ErrorOr<T> &E) {
104   FailIfError(E.getError());
105 }
106
107 static void FailIfNotEmpty(const std::string &E) {
108   if (E.empty())
109     return;
110   errs() << "Error: " << E << "\n";
111   exit(1);
112 }
113
114 template <typename T>
115 static void FailIfEmpty(const std::unique_ptr<T> &Ptr,
116                         const std::string &Message) {
117   if (Ptr.get())
118     return;
119   errs() << "Error: " << Message << "\n";
120   exit(1);
121 }
122
123 template <typename T>
124 static void readInts(const char *Start, const char *End,
125                      std::set<uint64_t> *Ints) {
126   const T *S = reinterpret_cast<const T *>(Start);
127   const T *E = reinterpret_cast<const T *>(End);
128   std::copy(S, E, std::inserter(*Ints, Ints->end()));
129 }
130
131 struct FileLoc {
132   bool operator<(const FileLoc &RHS) const {
133     return std::tie(FileName, Line) < std::tie(RHS.FileName, RHS.Line);
134   }
135
136   std::string FileName;
137   uint32_t Line;
138 };
139
140 struct FunctionLoc {
141   bool operator<(const FunctionLoc &RHS) const {
142     return std::tie(Loc, FunctionName) < std::tie(RHS.Loc, RHS.FunctionName);
143   }
144
145   FileLoc Loc;
146   std::string FunctionName;
147 };
148
149 std::string stripPathPrefix(std::string Path) {
150   if (ClStripPathPrefix.empty())
151     return Path;
152   size_t Pos = Path.find(ClStripPathPrefix);
153   if (Pos == std::string::npos)
154     return Path;
155   return Path.substr(Pos + ClStripPathPrefix.size());
156 }
157
158 // Compute [FileLoc -> FunctionName] map for given addresses.
159 static std::map<FileLoc, std::string>
160 computeFunctionsMap(const std::set<uint64_t> &Addrs) {
161   std::map<FileLoc, std::string> Fns;
162
163   symbolize::LLVMSymbolizer::Options SymbolizerOptions;
164   SymbolizerOptions.Demangle = ClDemangle;
165   SymbolizerOptions.UseSymbolTable = true;
166   symbolize::LLVMSymbolizer Symbolizer(SymbolizerOptions);
167
168   // Fill in Fns map.
169   for (auto Addr : Addrs) {
170     auto InliningInfo = Symbolizer.symbolizeInlinedCode(ClBinaryName, Addr);
171     FailIfError(InliningInfo);
172     for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) {
173       auto FrameInfo = InliningInfo->getFrame(i);
174       SmallString<256> FileName(FrameInfo.FileName);
175       sys::path::remove_dots(FileName, /* remove_dot_dot */ true);
176       FileLoc Loc = {FileName.str(), FrameInfo.Line};
177       Fns[Loc] = FrameInfo.FunctionName;
178     }
179   }
180
181   return Fns;
182 }
183
184 // Compute functions for given addresses. It keeps only the first
185 // occurence of a function within a file.
186 std::set<FunctionLoc> computeFunctionLocs(const std::set<uint64_t> &Addrs) {
187   std::map<FileLoc, std::string> Fns = computeFunctionsMap(Addrs);
188
189   std::set<FunctionLoc> result;
190   std::string LastFileName;
191   std::set<std::string> ProcessedFunctions;
192
193   for (const auto &P : Fns) {
194     std::string FileName = P.first.FileName;
195     std::string FunctionName = P.second;
196
197     if (LastFileName != FileName)
198       ProcessedFunctions.clear();
199     LastFileName = FileName;
200
201     if (!ProcessedFunctions.insert(FunctionName).second)
202       continue;
203
204     result.insert(FunctionLoc{P.first, P.second});
205   }
206
207   return result;
208 }
209
210 // Locate __sanitizer_cov* function addresses that are used for coverage
211 // reporting.
212 static std::set<uint64_t>
213 findSanitizerCovFunctions(const object::ObjectFile &O) {
214   std::set<uint64_t> Result;
215
216   for (const object::SymbolRef &Symbol : O.symbols()) {
217     ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
218     FailIfError(AddressOrErr);
219
220     ErrorOr<StringRef> NameOrErr = Symbol.getName();
221     FailIfError(NameOrErr);
222     StringRef Name = NameOrErr.get();
223
224     if (Name == "__sanitizer_cov" || Name == "__sanitizer_cov_with_check" ||
225         Name == "__sanitizer_cov_trace_func_enter") {
226       Result.insert(AddressOrErr.get());
227     }
228   }
229
230   if (Result.empty())
231     FailIfNotEmpty("__sanitizer_cov* functions not found");
232
233   return Result;
234 }
235
236 // Locate addresses of all coverage points in a file. Coverage point
237 // is defined as the 'address of instruction following __sanitizer_cov
238 // call - 1'.
239 static void getObjectCoveragePoints(const object::ObjectFile &O,
240                                     std::set<uint64_t> *Addrs) {
241   Triple TheTriple("unknown-unknown-unknown");
242   TheTriple.setArch(Triple::ArchType(O.getArch()));
243   auto TripleName = TheTriple.getTriple();
244
245   std::string Error;
246   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
247   FailIfNotEmpty(Error);
248
249   std::unique_ptr<const MCSubtargetInfo> STI(
250       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
251   FailIfEmpty(STI, "no subtarget info for target " + TripleName);
252
253   std::unique_ptr<const MCRegisterInfo> MRI(
254       TheTarget->createMCRegInfo(TripleName));
255   FailIfEmpty(MRI, "no register info for target " + TripleName);
256
257   std::unique_ptr<const MCAsmInfo> AsmInfo(
258       TheTarget->createMCAsmInfo(*MRI, TripleName));
259   FailIfEmpty(AsmInfo, "no asm info for target " + TripleName);
260
261   std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
262   MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
263   std::unique_ptr<MCDisassembler> DisAsm(
264       TheTarget->createMCDisassembler(*STI, Ctx));
265   FailIfEmpty(DisAsm, "no disassembler info for target " + TripleName);
266
267   std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
268   FailIfEmpty(MII, "no instruction info for target " + TripleName);
269
270   std::unique_ptr<const MCInstrAnalysis> MIA(
271       TheTarget->createMCInstrAnalysis(MII.get()));
272   FailIfEmpty(MIA, "no instruction analysis info for target " + TripleName);
273
274   auto SanCovAddrs = findSanitizerCovFunctions(O);
275
276   for (const auto Section : O.sections()) {
277     if (Section.isVirtual() || !Section.isText()) // llvm-objdump does the same.
278       continue;
279     uint64_t SectionAddr = Section.getAddress();
280     uint64_t SectSize = Section.getSize();
281     if (!SectSize)
282       continue;
283
284     StringRef SectionName;
285     FailIfError(Section.getName(SectionName));
286
287     StringRef BytesStr;
288     FailIfError(Section.getContents(BytesStr));
289     ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
290                             BytesStr.size());
291
292     for (uint64_t Index = 0, Size = 0; Index < Section.getSize();
293          Index += Size) {
294       MCInst Inst;
295       if (!DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
296                                   SectionAddr + Index, nulls(), nulls())) {
297         if (Size == 0)
298           Size = 1;
299         continue;
300       }
301       uint64_t Target;
302       if (MIA->isCall(Inst) &&
303           MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) {
304         if (SanCovAddrs.find(Target) != SanCovAddrs.end()) {
305           // Sanitizer coverage uses the address of the next instruction - 1.
306           Addrs->insert(Index + SectionAddr + Size - 1);
307         }
308       }
309     }
310   }
311 }
312
313 static void getArchiveCoveragePoints(const object::Archive &A,
314                                      std::set<uint64_t> *Addrs) {
315   for (auto &ErrorOrChild : A.children()) {
316     FailIfError(ErrorOrChild);
317     const object::Archive::Child &C = *ErrorOrChild;
318     ErrorOr<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary();
319     FailIfError(ChildOrErr);
320     if (object::ObjectFile *O =
321             dyn_cast<object::ObjectFile>(&*ChildOrErr.get()))
322       getObjectCoveragePoints(*O, Addrs);
323     else
324       FailIfError(object::object_error::invalid_file_type);
325   }
326 }
327
328 // Locate addresses of all coverage points in a file. Coverage point
329 // is defined as the 'address of instruction following __sanitizer_cov
330 // call - 1'.
331 std::set<uint64_t> getCoveragePoints(std::string FileName) {
332   std::set<uint64_t> Result;
333
334   ErrorOr<object::OwningBinary<object::Binary>> BinaryOrErr =
335       object::createBinary(FileName);
336   FailIfError(BinaryOrErr);
337
338   object::Binary &Binary = *BinaryOrErr.get().getBinary();
339   if (object::Archive *A = dyn_cast<object::Archive>(&Binary))
340     getArchiveCoveragePoints(*A, &Result);
341   else if (object::ObjectFile *O = dyn_cast<object::ObjectFile>(&Binary))
342     getObjectCoveragePoints(*O, &Result);
343   else
344     FailIfError(object::object_error::invalid_file_type);
345
346   return Result;
347 }
348
349 static void printFunctionLocs(const std::set<FunctionLoc> &FnLocs,
350                               raw_ostream &OS) {
351   for (const FunctionLoc &FnLoc : FnLocs) {
352     OS << stripPathPrefix(FnLoc.Loc.FileName) << ":" << FnLoc.Loc.Line << " "
353        << FnLoc.FunctionName << "\n";
354   }
355 }
356
357 class CoverageData {
358  public:
359   // Read single file coverage data.
360   static ErrorOr<std::unique_ptr<CoverageData>> read(std::string FileName) {
361     ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
362         MemoryBuffer::getFile(FileName);
363     if (!BufOrErr)
364       return BufOrErr.getError();
365     std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
366     if (Buf->getBufferSize() < 8) {
367       errs() << "File too small (<8): " << Buf->getBufferSize();
368       return make_error_code(errc::illegal_byte_sequence);
369     }
370     const FileHeader *Header =
371         reinterpret_cast<const FileHeader *>(Buf->getBufferStart());
372
373     if (Header->Magic != BinCoverageMagic) {
374       errs() << "Wrong magic: " << Header->Magic;
375       return make_error_code(errc::illegal_byte_sequence);
376     }
377
378     auto Addrs = llvm::make_unique<std::set<uint64_t>>();
379
380     switch (Header->Bitness) {
381     case Bitness64:
382       readInts<uint64_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),
383                          Addrs.get());
384       break;
385     case Bitness32:
386       readInts<uint32_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),
387                          Addrs.get());
388       break;
389     default:
390       errs() << "Unsupported bitness: " << Header->Bitness;
391       return make_error_code(errc::illegal_byte_sequence);
392     }
393
394     return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));
395   }
396
397   // Merge multiple coverage data together.
398   static std::unique_ptr<CoverageData>
399   merge(const std::vector<std::unique_ptr<CoverageData>> &Covs) {
400     auto Addrs = llvm::make_unique<std::set<uint64_t>>();
401
402     for (const auto &Cov : Covs)
403       Addrs->insert(Cov->Addrs->begin(), Cov->Addrs->end());
404
405     return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));
406   }
407
408   // Read list of files and merges their coverage info.
409   static ErrorOr<std::unique_ptr<CoverageData>>
410   readAndMerge(const std::vector<std::string> &FileNames) {
411     std::vector<std::unique_ptr<CoverageData>> Covs;
412     for (const auto &FileName : FileNames) {
413       auto Cov = read(FileName);
414       if (!Cov)
415         return Cov.getError();
416       Covs.push_back(std::move(Cov.get()));
417     }
418     return merge(Covs);
419   }
420
421   // Print coverage addresses.
422   void printAddrs(raw_ostream &OS) {
423     for (auto Addr : *Addrs) {
424       OS << "0x";
425       OS.write_hex(Addr);
426       OS << "\n";
427     }
428   }
429
430   // Print list of covered functions.
431   // Line format: <file_name>:<line> <function_name>
432   void printCoveredFunctions(raw_ostream &OS) {
433     printFunctionLocs(computeFunctionLocs(*Addrs), OS);
434   }
435
436   // Print list of not covered functions.
437   // Line format: <file_name>:<line> <function_name>
438   void printNotCoveredFunctions(raw_ostream &OS) {
439     std::set<FunctionLoc> AllFns =
440         computeFunctionLocs(getCoveragePoints(ClBinaryName));
441     std::set<FunctionLoc> CoveredFns = computeFunctionLocs(*Addrs);
442
443     std::set<FunctionLoc> NotCoveredFns;
444     std::set_difference(AllFns.begin(), AllFns.end(), CoveredFns.begin(),
445                         CoveredFns.end(),
446                         std::inserter(NotCoveredFns, NotCoveredFns.end()));
447     printFunctionLocs(NotCoveredFns, OS);
448   }
449
450 private:
451   explicit CoverageData(std::unique_ptr<std::set<uint64_t>> Addrs)
452       : Addrs(std::move(Addrs)) {}
453
454   std::unique_ptr<std::set<uint64_t>> Addrs;
455 };
456 } // namespace
457
458 int main(int argc, char **argv) {
459   // Print stack trace if we signal out.
460   sys::PrintStackTraceOnErrorSignal();
461   PrettyStackTraceProgram X(argc, argv);
462   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
463
464   llvm::InitializeAllTargetInfos();
465   llvm::InitializeAllTargetMCs();
466   llvm::InitializeAllDisassemblers();
467
468   cl::ParseCommandLineOptions(argc, argv, "Sanitizer Coverage Processing Tool");
469
470   auto CovData = CoverageData::readAndMerge(ClInputFiles);
471   FailIfError(CovData);
472
473   switch (Action) {
474   case PrintAction: {
475     CovData.get()->printAddrs(outs());
476     return 0;
477   }
478   case CoveredFunctionsAction: {
479     CovData.get()->printCoveredFunctions(outs());
480     return 0;
481   }
482   case NotCoveredFunctionsAction: {
483     CovData.get()->printNotCoveredFunctions(outs());
484     return 0;
485   }
486   }
487
488   llvm_unreachable("unsupported action");
489 }