<div dir="ltr">Fixed in r282727. Thanks.</div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 28, 2016 at 8:22 PM Vitaly Buka <<a href="mailto:vitalybuka@google.com">vitalybuka@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">Bot is broken <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/25474/steps/run%20asan-dynamic%20tests/logs/stdio" class="gmail_msg" target="_blank">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/25474/steps/run%20asan-dynamic%20tests/logs/stdio</a></div><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Wed, Sep 28, 2016 at 2:48 PM Mike Aizatsky via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: aizatsky<br class="gmail_msg">
Date: Wed Sep 28 16:39:28 2016<br class="gmail_msg">
New Revision: 282639<br class="gmail_msg">
<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=282639&view=rev" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project?rev=282639&view=rev</a><br class="gmail_msg">
Log:<br class="gmail_msg">
[sancov] introducing symbolized coverage files (.symcov)<br class="gmail_msg">
<br class="gmail_msg">
Summary:<br class="gmail_msg">
Answering any meaningful questions about .sancov files requires<br class="gmail_msg">
accessing symbol information from the corresponding binary.<br class="gmail_msg">
<br class="gmail_msg">
This change introduces a separate intermediate data structure and<br class="gmail_msg">
format: symbolized coverage. It contains all symbol information that<br class="gmail_msg">
is required to answer common queries:<br class="gmail_msg">
- merging<br class="gmail_msg">
- coverd/uncovered files and functions<br class="gmail_msg">
- line status.<br class="gmail_msg">
<br class="gmail_msg">
Also removing the html report functionality from sancov: generated<br class="gmail_msg">
HTML files are too huge, and a different approach is required.<br class="gmail_msg">
Maintaining this half-working approach in the C++ is painful.<br class="gmail_msg">
<br class="gmail_msg">
Differential Revision: <a href="https://reviews.llvm.org/D24947" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D24947</a><br class="gmail_msg">
<br class="gmail_msg">
Added:<br class="gmail_msg">
llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov<br class="gmail_msg">
llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov<br class="gmail_msg">
llvm/trunk/test/tools/sancov/merge.test<br class="gmail_msg">
llvm/trunk/test/tools/sancov/symbolize.test<br class="gmail_msg">
Removed:<br class="gmail_msg">
llvm/trunk/test/tools/sancov/html-report.test<br class="gmail_msg">
Modified:<br class="gmail_msg">
llvm/trunk/include/llvm/DebugInfo/DIContext.h<br class="gmail_msg">
llvm/trunk/tools/sancov/sancov.cc<br class="gmail_msg">
<br class="gmail_msg">
Modified: llvm/trunk/include/llvm/DebugInfo/DIContext.h<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DIContext.h?rev=282639&r1=282638&r2=282639&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DIContext.h?rev=282639&r1=282638&r2=282639&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/include/llvm/DebugInfo/DIContext.h (original)<br class="gmail_msg">
+++ llvm/trunk/include/llvm/DebugInfo/DIContext.h Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -42,6 +42,10 @@ struct DILineInfo {<br class="gmail_msg">
bool operator!=(const DILineInfo &RHS) const {<br class="gmail_msg">
return !(*this == RHS);<br class="gmail_msg">
}<br class="gmail_msg">
+ bool operator<(const DILineInfo &RHS) const {<br class="gmail_msg">
+ return std::tie(FileName, FunctionName, Line, Column) <<br class="gmail_msg">
+ std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column);<br class="gmail_msg">
+ }<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable;<br class="gmail_msg">
<br class="gmail_msg">
Added: llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov?rev=282639&view=auto" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov?rev=282639&view=auto</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov (added)<br class="gmail_msg">
+++ llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.0.symcov Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -0,0 +1,25 @@<br class="gmail_msg">
+{<br class="gmail_msg">
+ "covered-points" : ["4e132b", "4e1472", "4e1520", "4e1553", "4e1586"],<br class="gmail_msg">
+ "binary-hash" : "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5",<br class="gmail_msg">
+ "point-symbol-info" : {<br class="gmail_msg">
+ "test/tools/sancov/Inputs/foo.cpp" : {<br class="gmail_msg">
+ "foo()" : {<br class="gmail_msg">
+ "4e178c" : "5:0"<br class="gmail_msg">
+ }<br class="gmail_msg">
+ },<br class="gmail_msg">
+ "test/tools/sancov/Inputs/test.cpp" : {<br class="gmail_msg">
+ "bar(std::string)" : {<br class="gmail_msg">
+ "4e132b" : "12:0"<br class="gmail_msg">
+ },<br class="gmail_msg">
+ "main" : {<br class="gmail_msg">
+ "4e1472" : "14:0",<br class="gmail_msg">
+ "4e14c2" : "16:9",<br class="gmail_msg">
+ "4e1520" : "17:5",<br class="gmail_msg">
+ "4e1553" : "17:5",<br class="gmail_msg">
+ "4e1586" : "17:5",<br class="gmail_msg">
+ "4e1635" : "19:1",<br class="gmail_msg">
+ "4e1690" : "17:5"<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
Added: llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov?rev=282639&view=auto" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov?rev=282639&view=auto</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov (added)<br class="gmail_msg">
+++ llvm/trunk/test/tools/sancov/Inputs/test-linux_x86_64.1.symcov Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -0,0 +1,25 @@<br class="gmail_msg">
+{<br class="gmail_msg">
+ "covered-points" : ["4e132b", "4e1472", "4e14c2", "4e1520", "4e1553", "4e1586", "4e178c"],<br class="gmail_msg">
+ "binary-hash" : "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5",<br class="gmail_msg">
+ "point-symbol-info" : {<br class="gmail_msg">
+ "test/tools/sancov/Inputs/foo.cpp" : {<br class="gmail_msg">
+ "foo()" : {<br class="gmail_msg">
+ "4e178c" : "5:0"<br class="gmail_msg">
+ }<br class="gmail_msg">
+ },<br class="gmail_msg">
+ "test/tools/sancov/Inputs/test.cpp" : {<br class="gmail_msg">
+ "bar(std::string)" : {<br class="gmail_msg">
+ "4e132b" : "12:0"<br class="gmail_msg">
+ },<br class="gmail_msg">
+ "main" : {<br class="gmail_msg">
+ "4e1472" : "14:0",<br class="gmail_msg">
+ "4e14c2" : "16:9",<br class="gmail_msg">
+ "4e1520" : "17:5",<br class="gmail_msg">
+ "4e1553" : "17:5",<br class="gmail_msg">
+ "4e1586" : "17:5",<br class="gmail_msg">
+ "4e1635" : "19:1",<br class="gmail_msg">
+ "4e1690" : "17:5"<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
Removed: llvm/trunk/test/tools/sancov/html-report.test<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/html-report.test?rev=282638&view=auto" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/html-report.test?rev=282638&view=auto</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/test/tools/sancov/html-report.test (original)<br class="gmail_msg">
+++ llvm/trunk/test/tools/sancov/html-report.test (removed)<br class="gmail_msg">
@@ -1,6 +0,0 @@<br class="gmail_msg">
-REQUIRES: x86_64-linux<br class="gmail_msg">
-RUN: sancov -html-report %p/Inputs/test-linux_x86_64 %p/Inputs/test-linux_x86_64.0.sancov | FileCheck %s<br class="gmail_msg">
-<br class="gmail_msg">
-// It's very difficult to test html report. Do basic smoke check.<br class="gmail_msg">
-CHECK: {{.*/Inputs/test.cpp}}<br class="gmail_msg">
-<br class="gmail_msg">
<br class="gmail_msg">
Added: llvm/trunk/test/tools/sancov/merge.test<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/merge.test?rev=282639&view=auto" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/merge.test?rev=282639&view=auto</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/test/tools/sancov/merge.test (added)<br class="gmail_msg">
+++ llvm/trunk/test/tools/sancov/merge.test Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -0,0 +1,64 @@<br class="gmail_msg">
+REQUIRES: x86_64-linux<br class="gmail_msg">
+RUN: sancov -merge %p/Inputs/test-linux_x86_64.0.symcov| FileCheck --check-prefix=MERGE1 %s<br class="gmail_msg">
+RUN: sancov -merge %p/Inputs/test-linux_x86_64.0.symcov %p/Inputs/test-linux_x86_64.1.symcov| FileCheck --check-prefix=MERGE2 %s<br class="gmail_msg">
+<br class="gmail_msg">
+MERGE1: {<br class="gmail_msg">
+MERGE1-NEXT: "covered-points" : ["4e132b", "4e1472", "4e1520", "4e1553", "4e1586"],<br class="gmail_msg">
+MERGE1-NEXT: "binary-hash" : "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5",<br class="gmail_msg">
+MERGE1-NEXT: "point-symbol-info" : {<br class="gmail_msg">
+MERGE1-NEXT: "test/tools/sancov/Inputs/foo.cpp" : {<br class="gmail_msg">
+MERGE1-NEXT: "foo()" : {<br class="gmail_msg">
+MERGE1-NEXT: "4e178c" : "5:0"<br class="gmail_msg">
+MERGE1-NEXT: }<br class="gmail_msg">
+MERGE1-NEXT: },<br class="gmail_msg">
+MERGE1-NEXT: "test/tools/sancov/Inputs/test.cpp" : {<br class="gmail_msg">
+MERGE1-NEXT: "bar(std::string)" : {<br class="gmail_msg">
+MERGE1-NEXT: "4e132b" : "12:0"<br class="gmail_msg">
+MERGE1-NEXT: },<br class="gmail_msg">
+MERGE1-NEXT: "main" : {<br class="gmail_msg">
+MERGE1-NEXT: "4e1472" : "14:0",<br class="gmail_msg">
+MERGE1-NEXT: "4e14c2" : "16:9",<br class="gmail_msg">
+MERGE1-NEXT: "4e1520" : "17:5",<br class="gmail_msg">
+MERGE1-NEXT: "4e1553" : "17:5",<br class="gmail_msg">
+MERGE1-NEXT: "4e1586" : "17:5",<br class="gmail_msg">
+MERGE1-NEXT: "4e1635" : "19:1",<br class="gmail_msg">
+MERGE1-NEXT: "4e1690" : "17:5"<br class="gmail_msg">
+MERGE1-NEXT: }<br class="gmail_msg">
+MERGE1-NEXT: }<br class="gmail_msg">
+MERGE1-NEXT: }<br class="gmail_msg">
+MERGE1-NEXT: }<br class="gmail_msg">
+<br class="gmail_msg">
+MERGE2: {<br class="gmail_msg">
+MERGE2-NEXT: "covered-points" : ["BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e132b", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1472", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e14c2", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1520", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1553", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1586", "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e178c"],<br class="gmail_msg">
+MERGE2-NEXT: "point-symbol-info" : {<br class="gmail_msg">
+MERGE2-NEXT: "test/tools/sancov/Inputs/foo.cpp" : {<br class="gmail_msg">
+MERGE2-NEXT: "foo()" : {<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e178c" : "5:0",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e178c" : "5:0"<br class="gmail_msg">
+MERGE2-NEXT: }<br class="gmail_msg">
+MERGE2-NEXT: },<br class="gmail_msg">
+MERGE2-NEXT: "test/tools/sancov/Inputs/test.cpp" : {<br class="gmail_msg">
+MERGE2-NEXT: "bar(std::string)" : {<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e132b" : "12:0",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e132b" : "12:0"<br class="gmail_msg">
+MERGE2-NEXT: },<br class="gmail_msg">
+MERGE2-NEXT: "main" : {<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1472" : "14:0",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e14c2" : "16:9",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1520" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1553" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1586" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1635" : "19:1",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1690" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1472" : "14:0",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e14c2" : "16:9",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1520" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1553" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1586" : "17:5",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1635" : "19:1",<br class="gmail_msg">
+MERGE2-NEXT: "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5:4e1690" : "17:5"<br class="gmail_msg">
+MERGE2-NEXT: }<br class="gmail_msg">
+MERGE2-NEXT: }<br class="gmail_msg">
+MERGE2-NEXT: }<br class="gmail_msg">
+MERGE2-NEXT: }<br class="gmail_msg">
+<br class="gmail_msg">
<br class="gmail_msg">
Added: llvm/trunk/test/tools/sancov/symbolize.test<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/symbolize.test?rev=282639&view=auto" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sancov/symbolize.test?rev=282639&view=auto</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/test/tools/sancov/symbolize.test (added)<br class="gmail_msg">
+++ llvm/trunk/test/tools/sancov/symbolize.test Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -0,0 +1,29 @@<br class="gmail_msg">
+REQUIRES: x86_64-linux<br class="gmail_msg">
+RUN: sancov -symbolize -strip_path_prefix="llvm/" %p/Inputs/test-linux_x86_64 %p/Inputs/test-linux_x86_64.0.sancov | FileCheck %s<br class="gmail_msg">
+<br class="gmail_msg">
+CHECK: {<br class="gmail_msg">
+CHECK-NEXT: "covered-points" : ["4e132b", "4e1472", "4e1520", "4e1553", "4e1586"],<br class="gmail_msg">
+CHECK-NEXT: "binary-hash" : "BB3CDD5045AED83906F6ADCC1C4DAF7E2596A6B5",<br class="gmail_msg">
+CHECK-NEXT: "point-symbol-info" : {<br class="gmail_msg">
+CHECK-NEXT: "test/tools/sancov/Inputs/foo.cpp" : {<br class="gmail_msg">
+CHECK-NEXT: "foo()" : {<br class="gmail_msg">
+CHECK-NEXT: "4e178c" : "5:0"<br class="gmail_msg">
+CHECK-NEXT: }<br class="gmail_msg">
+CHECK-NEXT: },<br class="gmail_msg">
+CHECK-NEXT: "test/tools/sancov/Inputs/test.cpp" : {<br class="gmail_msg">
+CHECK-NEXT: "bar(std::string)" : {<br class="gmail_msg">
+CHECK-NEXT: "4e132b" : "12:0"<br class="gmail_msg">
+CHECK-NEXT: },<br class="gmail_msg">
+CHECK-NEXT: "main" : {<br class="gmail_msg">
+CHECK-NEXT: "4e1472" : "14:0",<br class="gmail_msg">
+CHECK-NEXT: "4e14c2" : "16:9",<br class="gmail_msg">
+CHECK-NEXT: "4e1520" : "17:5",<br class="gmail_msg">
+CHECK-NEXT: "4e1553" : "17:5",<br class="gmail_msg">
+CHECK-NEXT: "4e1586" : "17:5",<br class="gmail_msg">
+CHECK-NEXT: "4e1635" : "19:1",<br class="gmail_msg">
+CHECK-NEXT: "4e1690" : "17:5"<br class="gmail_msg">
+CHECK-NEXT: }<br class="gmail_msg">
+CHECK-NEXT: }<br class="gmail_msg">
+CHECK-NEXT: }<br class="gmail_msg">
+CHECK-NEXT:}<br class="gmail_msg">
+<br class="gmail_msg">
<br class="gmail_msg">
Modified: llvm/trunk/tools/sancov/sancov.cc<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sancov/sancov.cc?rev=282639&r1=282638&r2=282639&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sancov/sancov.cc?rev=282639&r1=282638&r2=282639&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/tools/sancov/sancov.cc (original)<br class="gmail_msg">
+++ llvm/trunk/tools/sancov/sancov.cc Wed Sep 28 16:39:28 2016<br class="gmail_msg">
@@ -11,6 +11,7 @@<br class="gmail_msg">
// coverage.<br class="gmail_msg">
//===----------------------------------------------------------------------===//<br class="gmail_msg">
#include "llvm/ADT/STLExtras.h"<br class="gmail_msg">
+#include "llvm/ADT/StringExtras.h"<br class="gmail_msg">
#include "llvm/ADT/Twine.h"<br class="gmail_msg">
#include "llvm/DebugInfo/Symbolize/Symbolize.h"<br class="gmail_msg">
#include "llvm/MC/MCAsmInfo.h"<br class="gmail_msg">
@@ -41,11 +42,14 @@<br class="gmail_msg">
#include "llvm/Support/Path.h"<br class="gmail_msg">
#include "llvm/Support/PrettyStackTrace.h"<br class="gmail_msg">
#include "llvm/Support/Regex.h"<br class="gmail_msg">
+#include "llvm/Support/SHA1.h"<br class="gmail_msg">
#include "llvm/Support/Signals.h"<br class="gmail_msg">
+#include "llvm/Support/SourceMgr.h"<br class="gmail_msg">
#include "llvm/Support/SpecialCaseList.h"<br class="gmail_msg">
#include "llvm/Support/TargetRegistry.h"<br class="gmail_msg">
#include "llvm/Support/TargetSelect.h"<br class="gmail_msg">
#include "llvm/Support/ToolOutputFile.h"<br class="gmail_msg">
+#include "llvm/Support/YAMLParser.h"<br class="gmail_msg">
#include "llvm/Support/raw_ostream.h"<br class="gmail_msg">
<br class="gmail_msg">
#include <algorithm><br class="gmail_msg">
@@ -62,28 +66,33 @@ namespace {<br class="gmail_msg">
// --------- COMMAND LINE FLAGS ---------<br class="gmail_msg">
<br class="gmail_msg">
enum ActionType {<br class="gmail_msg">
- PrintAction,<br class="gmail_msg">
- PrintCovPointsAction,<br class="gmail_msg">
CoveredFunctionsAction,<br class="gmail_msg">
- NotCoveredFunctionsAction,<br class="gmail_msg">
HtmlReportAction,<br class="gmail_msg">
- StatsAction<br class="gmail_msg">
+ MergeAction,<br class="gmail_msg">
+ NotCoveredFunctionsAction,<br class="gmail_msg">
+ PrintAction,<br class="gmail_msg">
+ PrintCovPointsAction,<br class="gmail_msg">
+ StatsAction,<br class="gmail_msg">
+ SymbolizeAction<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
cl::opt<ActionType> Action(<br class="gmail_msg">
cl::desc("Action (required)"), cl::Required,<br class="gmail_msg">
- cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"),<br class="gmail_msg">
- clEnumValN(PrintCovPointsAction, "print-coverage-pcs",<br class="gmail_msg">
- "Print coverage instrumentation points addresses."),<br class="gmail_msg">
- clEnumValN(CoveredFunctionsAction, "covered-functions",<br class="gmail_msg">
- "Print all covered funcions."),<br class="gmail_msg">
- clEnumValN(NotCoveredFunctionsAction, "not-covered-functions",<br class="gmail_msg">
- "Print all not covered funcions."),<br class="gmail_msg">
- clEnumValN(HtmlReportAction, "html-report",<br class="gmail_msg">
- "Print HTML coverage report."),<br class="gmail_msg">
- clEnumValN(StatsAction, "print-coverage-stats",<br class="gmail_msg">
- "Print coverage statistics."),<br class="gmail_msg">
- clEnumValEnd));<br class="gmail_msg">
+ cl::values(<br class="gmail_msg">
+ clEnumValN(PrintAction, "print", "Print coverage addresses"),<br class="gmail_msg">
+ clEnumValN(PrintCovPointsAction, "print-coverage-pcs",<br class="gmail_msg">
+ "Print coverage instrumentation points addresses."),<br class="gmail_msg">
+ clEnumValN(CoveredFunctionsAction, "covered-functions",<br class="gmail_msg">
+ "Print all covered funcions."),<br class="gmail_msg">
+ clEnumValN(NotCoveredFunctionsAction, "not-covered-functions",<br class="gmail_msg">
+ "Print all not covered funcions."),<br class="gmail_msg">
+ clEnumValN(StatsAction, "print-coverage-stats",<br class="gmail_msg">
+ "Print coverage statistics."),<br class="gmail_msg">
+ clEnumValN(HtmlReportAction, "html-report",<br class="gmail_msg">
+ "REMOVED. Use -symbolize & symcov-report-server.py."),<br class="gmail_msg">
+ clEnumValN(SymbolizeAction, "symbolize",<br class="gmail_msg">
+ "Produces a symbolized JSON report from binary report."),<br class="gmail_msg">
+ clEnumValN(MergeAction, "merge", "Merges reports."), clEnumValEnd));<br class="gmail_msg">
<br class="gmail_msg">
static cl::list<std::string><br class="gmail_msg">
ClInputFiles(cl::Positional, cl::OneOrMore,<br class="gmail_msg">
@@ -119,66 +128,99 @@ static const uint32_t BinCoverageMagic =<br class="gmail_msg">
static const uint32_t Bitness32 = 0xFFFFFF32;<br class="gmail_msg">
static const uint32_t Bitness64 = 0xFFFFFF64;<br class="gmail_msg">
<br class="gmail_msg">
+static Regex SancovFileRegex("(.*)\\.[0-9]+\\.sancov");<br class="gmail_msg">
+static Regex SymcovFileRegex(".*\\.symcov");<br class="gmail_msg">
+<br class="gmail_msg">
+// --------- MAIN DATASTRUCTURES ----------<br class="gmail_msg">
+<br class="gmail_msg">
+// Contents of .sancov file: list of coverage point addresses that were<br class="gmail_msg">
+// executed.<br class="gmail_msg">
+struct RawCoverage {<br class="gmail_msg">
+ explicit RawCoverage(std::unique_ptr<std::set<uint64_t>> Addrs)<br class="gmail_msg">
+ : Addrs(std::move(Addrs)) {}<br class="gmail_msg">
+<br class="gmail_msg">
+ // Read binary .sancov file.<br class="gmail_msg">
+ static ErrorOr<std::unique_ptr<RawCoverage>><br class="gmail_msg">
+ read(const std::string &FileName);<br class="gmail_msg">
+<br class="gmail_msg">
+ std::unique_ptr<std::set<uint64_t>> Addrs;<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
+// Coverage point has an opaque Id and corresponds to multiple source locations.<br class="gmail_msg">
+struct CoveragePoint {<br class="gmail_msg">
+ explicit CoveragePoint(const std::string &Id) : Id(Id) {}<br class="gmail_msg">
+<br class="gmail_msg">
+ std::string Id;<br class="gmail_msg">
+ SmallVector<DILineInfo, 1> Locs;<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
+// Symcov file content: set of covered Ids plus information about all available<br class="gmail_msg">
+// coverage points.<br class="gmail_msg">
+struct SymbolizedCoverage {<br class="gmail_msg">
+ // Read json .symcov file.<br class="gmail_msg">
+ static std::unique_ptr<SymbolizedCoverage> read(const std::string &InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ std::set<std::string> CoveredIds;<br class="gmail_msg">
+ std::string BinaryHash;<br class="gmail_msg">
+ std::vector<CoveragePoint> Points;<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
+struct CoverageStats {<br class="gmail_msg">
+ size_t AllPoints;<br class="gmail_msg">
+ size_t CovPoints;<br class="gmail_msg">
+ size_t AllFns;<br class="gmail_msg">
+ size_t CovFns;<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
// --------- ERROR HANDLING ---------<br class="gmail_msg">
<br class="gmail_msg">
-static void Fail(const llvm::Twine &E) {<br class="gmail_msg">
+static void fail(const llvm::Twine &E) {<br class="gmail_msg">
errs() << "Error: " << E << "\n";<br class="gmail_msg">
exit(1);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-static void FailIfError(std::error_code Error) {<br class="gmail_msg">
+static void failIf(bool B, const llvm::Twine &E) {<br class="gmail_msg">
+ if (B)<br class="gmail_msg">
+ fail(E);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+static void failIfError(std::error_code Error) {<br class="gmail_msg">
if (!Error)<br class="gmail_msg">
return;<br class="gmail_msg">
errs() << "Error: " << Error.message() << "(" << Error.value() << ")\n";<br class="gmail_msg">
exit(1);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-template <typename T> static void FailIfError(const ErrorOr<T> &E) {<br class="gmail_msg">
- FailIfError(E.getError());<br class="gmail_msg">
+template <typename T> static void failIfError(const ErrorOr<T> &E) {<br class="gmail_msg">
+ failIfError(E.getError());<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-static void FailIfError(Error Err) {<br class="gmail_msg">
+static void failIfError(Error Err) {<br class="gmail_msg">
if (Err) {<br class="gmail_msg">
logAllUnhandledErrors(std::move(Err), errs(), "Error: ");<br class="gmail_msg">
exit(1);<br class="gmail_msg">
}<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-template <typename T> static void FailIfError(Expected<T> &E) {<br class="gmail_msg">
- FailIfError(E.takeError());<br class="gmail_msg">
+template <typename T> static void failIfError(Expected<T> &E) {<br class="gmail_msg">
+ failIfError(E.takeError());<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-static void FailIfNotEmpty(const llvm::Twine &E) {<br class="gmail_msg">
+static void failIfNotEmpty(const llvm::Twine &E) {<br class="gmail_msg">
if (E.str().empty())<br class="gmail_msg">
return;<br class="gmail_msg">
- Fail(E);<br class="gmail_msg">
+ fail(E);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
template <typename T><br class="gmail_msg">
-static void FailIfEmpty(const std::unique_ptr<T> &Ptr,<br class="gmail_msg">
+static void failIfEmpty(const std::unique_ptr<T> &Ptr,<br class="gmail_msg">
const std::string &Message) {<br class="gmail_msg">
if (Ptr.get())<br class="gmail_msg">
return;<br class="gmail_msg">
- Fail(Message);<br class="gmail_msg">
-}<br class="gmail_msg">
-<br class="gmail_msg">
-// ---------<br class="gmail_msg">
-<br class="gmail_msg">
-// Produces std::map<K, std::vector<E>> grouping input<br class="gmail_msg">
-// elements by FuncTy result.<br class="gmail_msg">
-template <class RangeTy, class FuncTy><br class="gmail_msg">
-static inline auto group_by(const RangeTy &R, FuncTy F)<br class="gmail_msg">
- -> std::map<typename std::decay<decltype(F(*R.begin()))>::type,<br class="gmail_msg">
- std::vector<typename std::decay<decltype(*R.begin())>::type>> {<br class="gmail_msg">
- std::map<typename std::decay<decltype(F(*R.begin()))>::type,<br class="gmail_msg">
- std::vector<typename std::decay<decltype(*R.begin())>::type>><br class="gmail_msg">
- Result;<br class="gmail_msg">
- for (const auto &E : R) {<br class="gmail_msg">
- Result[F(E)].push_back(E);<br class="gmail_msg">
- }<br class="gmail_msg">
- return Result;<br class="gmail_msg">
+ fail(Message);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
+// ----------- Coverage I/O ----------<br class="gmail_msg">
template <typename T><br class="gmail_msg">
static void readInts(const char *Start, const char *End,<br class="gmail_msg">
std::set<uint64_t> *Ints) {<br class="gmail_msg">
@@ -187,34 +229,321 @@ static void readInts(const char *Start,<br class="gmail_msg">
std::copy(S, E, std::inserter(*Ints, Ints->end()));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-struct FileLoc {<br class="gmail_msg">
- bool operator<(const FileLoc &RHS) const {<br class="gmail_msg">
- return std::tie(FileName, Line) < std::tie(RHS.FileName, RHS.Line);<br class="gmail_msg">
+ErrorOr<std::unique_ptr<RawCoverage>><br class="gmail_msg">
+RawCoverage::read(const std::string &FileName) {<br class="gmail_msg">
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =<br class="gmail_msg">
+ MemoryBuffer::getFile(FileName);<br class="gmail_msg">
+ if (!BufOrErr)<br class="gmail_msg">
+ return BufOrErr.getError();<br class="gmail_msg">
+ std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());<br class="gmail_msg">
+ if (Buf->getBufferSize() < 8) {<br class="gmail_msg">
+ errs() << "File too small (<8): " << Buf->getBufferSize() << '\n';<br class="gmail_msg">
+ return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
}<br class="gmail_msg">
+ const FileHeader *Header =<br class="gmail_msg">
+ reinterpret_cast<const FileHeader *>(Buf->getBufferStart());<br class="gmail_msg">
<br class="gmail_msg">
- std::string FileName;<br class="gmail_msg">
- uint32_t Line;<br class="gmail_msg">
-};<br class="gmail_msg">
+ if (Header->Magic != BinCoverageMagic) {<br class="gmail_msg">
+ errs() << "Wrong magic: " << Header->Magic << '\n';<br class="gmail_msg">
+ return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
+ }<br class="gmail_msg">
<br class="gmail_msg">
-struct FileFn {<br class="gmail_msg">
- bool operator<(const FileFn &RHS) const {<br class="gmail_msg">
- return std::tie(FileName, FunctionName) <<br class="gmail_msg">
- std::tie(RHS.FileName, RHS.FunctionName);<br class="gmail_msg">
+ auto Addrs = llvm::make_unique<std::set<uint64_t>>();<br class="gmail_msg">
+<br class="gmail_msg">
+ switch (Header->Bitness) {<br class="gmail_msg">
+ case Bitness64:<br class="gmail_msg">
+ readInts<uint64_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),<br class="gmail_msg">
+ Addrs.get());<br class="gmail_msg">
+ break;<br class="gmail_msg">
+ case Bitness32:<br class="gmail_msg">
+ readInts<uint32_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),<br class="gmail_msg">
+ Addrs.get());<br class="gmail_msg">
+ break;<br class="gmail_msg">
+ default:<br class="gmail_msg">
+ errs() << "Unsupported bitness: " << Header->Bitness << '\n';<br class="gmail_msg">
+ return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
- std::string FileName;<br class="gmail_msg">
- std::string FunctionName;<br class="gmail_msg">
-};<br class="gmail_msg">
+ return std::unique_ptr<RawCoverage>(new RawCoverage(std::move(Addrs)));<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
-struct FnLoc {<br class="gmail_msg">
- bool operator<(const FnLoc &RHS) const {<br class="gmail_msg">
- return std::tie(Loc, FunctionName) < std::tie(RHS.Loc, RHS.FunctionName);<br class="gmail_msg">
+// Print coverage addresses.<br class="gmail_msg">
+raw_ostream &operator<<(raw_ostream &OS, const RawCoverage &CoverageData) {<br class="gmail_msg">
+ for (auto Addr : *CoverageData.Addrs) {<br class="gmail_msg">
+ OS << "0x";<br class="gmail_msg">
+ OS.write_hex(Addr);<br class="gmail_msg">
+ OS << "\n";<br class="gmail_msg">
}<br class="gmail_msg">
+ return OS;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
- FileLoc Loc;<br class="gmail_msg">
- std::string FunctionName;<br class="gmail_msg">
+static raw_ostream &operator<<(raw_ostream &OS, const CoverageStats &Stats) {<br class="gmail_msg">
+ OS << "all-edges: " << Stats.AllPoints << "\n";<br class="gmail_msg">
+ OS << "cov-edges: " << Stats.CovPoints << "\n";<br class="gmail_msg">
+ OS << "all-functions: " << Stats.AllFns << "\n";<br class="gmail_msg">
+ OS << "cov-functions: " << Stats.CovFns << "\n";<br class="gmail_msg">
+ return OS;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// Helper for writing out JSON. Handles indents and commas using<br class="gmail_msg">
+// scope variables for objects and arrays.<br class="gmail_msg">
+class JSONWriter {<br class="gmail_msg">
+public:<br class="gmail_msg">
+ JSONWriter(raw_ostream &Out) : OS(Out) {}<br class="gmail_msg">
+ JSONWriter(const JSONWriter &) = delete;<br class="gmail_msg">
+ ~JSONWriter() { OS << "\n"; }<br class="gmail_msg">
+<br class="gmail_msg">
+ void operator<<(StringRef S) { printJSONStringLiteral(S, OS); }<br class="gmail_msg">
+<br class="gmail_msg">
+ // Helper RAII class to output JSON objects.<br class="gmail_msg">
+ class Object {<br class="gmail_msg">
+ public:<br class="gmail_msg">
+ Object(JSONWriter *W, raw_ostream &OS) : W(W), OS(OS) {<br class="gmail_msg">
+ OS << "{";<br class="gmail_msg">
+ W->Indent++;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ Object(const Object &) = delete;<br class="gmail_msg">
+ ~Object() {<br class="gmail_msg">
+ W->Indent--;<br class="gmail_msg">
+ OS << "\n";<br class="gmail_msg">
+ W->indent();<br class="gmail_msg">
+ OS << "}";<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ void key(StringRef Key) {<br class="gmail_msg">
+ Index++;<br class="gmail_msg">
+ if (Index > 0)<br class="gmail_msg">
+ OS << ",";<br class="gmail_msg">
+ OS << "\n";<br class="gmail_msg">
+ W->indent();<br class="gmail_msg">
+ printJSONStringLiteral(Key, OS);<br class="gmail_msg">
+ OS << " : ";<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ private:<br class="gmail_msg">
+ JSONWriter *W;<br class="gmail_msg">
+ raw_ostream &OS;<br class="gmail_msg">
+ int Index = -1;<br class="gmail_msg">
+ };<br class="gmail_msg">
+<br class="gmail_msg">
+ std::unique_ptr<Object> object() { return make_unique<Object>(this, OS); }<br class="gmail_msg">
+<br class="gmail_msg">
+ // Helper RAII class to output JSON arrays.<br class="gmail_msg">
+ class Array {<br class="gmail_msg">
+ public:<br class="gmail_msg">
+ Array(raw_ostream &OS) : OS(OS) { OS << "["; }<br class="gmail_msg">
+ Array(const Array &) = delete;<br class="gmail_msg">
+ ~Array() { OS << "]"; }<br class="gmail_msg">
+ void next() {<br class="gmail_msg">
+ Index++;<br class="gmail_msg">
+ if (Index > 0)<br class="gmail_msg">
+ OS << ", ";<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ private:<br class="gmail_msg">
+ raw_ostream &OS;<br class="gmail_msg">
+ int Index = -1;<br class="gmail_msg">
+ };<br class="gmail_msg">
+<br class="gmail_msg">
+ std::unique_ptr<Array> array() { return make_unique<Array>(OS); }<br class="gmail_msg">
+<br class="gmail_msg">
+private:<br class="gmail_msg">
+ void indent() { OS.indent(Indent * 2); }<br class="gmail_msg">
+<br class="gmail_msg">
+ static void printJSONStringLiteral(StringRef S, raw_ostream &OS) {<br class="gmail_msg">
+ if (S.find('"') == std::string::npos) {<br class="gmail_msg">
+ OS << "\"" << S << "\"";<br class="gmail_msg">
+ return;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ OS << "\"";<br class="gmail_msg">
+ for (char Ch : S.bytes()) {<br class="gmail_msg">
+ if (Ch == '"')<br class="gmail_msg">
+ OS << "\\";<br class="gmail_msg">
+ OS << Ch;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ OS << "\"";<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ raw_ostream &OS;<br class="gmail_msg">
+ int Indent = 0;<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
+// Output symbolized information for coverage points in JSON.<br class="gmail_msg">
+// Format:<br class="gmail_msg">
+// {<br class="gmail_msg">
+// '<file_name>' : {<br class="gmail_msg">
+// '<function_name>' : {<br class="gmail_msg">
+// '<point_id'> : '<line_number>:'<column_number'.<br class="gmail_msg">
+// ....<br class="gmail_msg">
+// }<br class="gmail_msg">
+// }<br class="gmail_msg">
+// }<br class="gmail_msg">
+static void operator<<(JSONWriter &W,<br class="gmail_msg">
+ const std::vector<CoveragePoint> &Points) {<br class="gmail_msg">
+ // Group points by file.<br class="gmail_msg">
+ auto ByFile(W.object());<br class="gmail_msg">
+ std::map<std::string, std::vector<const CoveragePoint *>> PointsByFile;<br class="gmail_msg">
+ for (const auto &Point : Points) {<br class="gmail_msg">
+ for (const DILineInfo &Loc : Point.Locs) {<br class="gmail_msg">
+ PointsByFile[Loc.FileName].push_back(&Point);<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ for (const auto &P : PointsByFile) {<br class="gmail_msg">
+ std::string FileName = P.first;<br class="gmail_msg">
+ ByFile->key(FileName);<br class="gmail_msg">
+<br class="gmail_msg">
+ // Group points by function.<br class="gmail_msg">
+ auto ByFn(W.object());<br class="gmail_msg">
+ std::map<std::string, std::vector<const CoveragePoint *>> PointsByFn;<br class="gmail_msg">
+ for (auto PointPtr : P.second) {<br class="gmail_msg">
+ for (const DILineInfo &Loc : PointPtr->Locs) {<br class="gmail_msg">
+ PointsByFn[Loc.FunctionName].push_back(PointPtr);<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ for (const auto &P : PointsByFn) {<br class="gmail_msg">
+ std::string FunctionName = P.first;<br class="gmail_msg">
+ ByFn->key(FunctionName);<br class="gmail_msg">
+<br class="gmail_msg">
+ // Output <point_id> : "<line>:<col>".<br class="gmail_msg">
+ auto ById(W.object());<br class="gmail_msg">
+ for (const CoveragePoint *Point : P.second) {<br class="gmail_msg">
+ for (const auto &Loc : Point->Locs) {<br class="gmail_msg">
+ if (Loc.FileName != FileName || Loc.FunctionName != FunctionName)<br class="gmail_msg">
+ continue;<br class="gmail_msg">
+<br class="gmail_msg">
+ ById->key(Point->Id);<br class="gmail_msg">
+ W << (utostr(Loc.Line) + ":" + utostr(Loc.Column));<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+static void operator<<(JSONWriter &W, const SymbolizedCoverage &C) {<br class="gmail_msg">
+ auto O(W.object());<br class="gmail_msg">
+<br class="gmail_msg">
+ {<br class="gmail_msg">
+ O->key("covered-points");<br class="gmail_msg">
+ auto PointsArray(W.array());<br class="gmail_msg">
+<br class="gmail_msg">
+ for (const auto &P : C.CoveredIds) {<br class="gmail_msg">
+ PointsArray->next();<br class="gmail_msg">
+ W << P;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ {<br class="gmail_msg">
+ if (!C.BinaryHash.empty()) {<br class="gmail_msg">
+ O->key("binary-hash");<br class="gmail_msg">
+ W << C.BinaryHash;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ {<br class="gmail_msg">
+ O->key("point-symbol-info");<br class="gmail_msg">
+ W << C.Points;<br class="gmail_msg">
+ }<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+static std::string parseScalarString(yaml::Node *N) {<br class="gmail_msg">
+ SmallString<64> StringStorage;<br class="gmail_msg">
+ yaml::ScalarNode *S = dyn_cast<yaml::ScalarNode>(N);<br class="gmail_msg">
+ failIf(!S, "expected string");<br class="gmail_msg">
+ return S->getValue(StringStorage);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+std::unique_ptr<SymbolizedCoverage><br class="gmail_msg">
+SymbolizedCoverage::read(const std::string &InputFile) {<br class="gmail_msg">
+ auto Coverage(make_unique<SymbolizedCoverage>());<br class="gmail_msg">
+<br class="gmail_msg">
+ std::map<std::string, CoveragePoint> Points;<br class="gmail_msg">
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =<br class="gmail_msg">
+ MemoryBuffer::getFile(InputFile);<br class="gmail_msg">
+ failIfError(BufOrErr);<br class="gmail_msg">
+<br class="gmail_msg">
+ SourceMgr SM;<br class="gmail_msg">
+ yaml::Stream S(**BufOrErr, SM);<br class="gmail_msg">
+<br class="gmail_msg">
+ yaml::document_iterator DI = S.begin();<br class="gmail_msg">
+ failIf(DI == S.end(), "empty document: " + InputFile);<br class="gmail_msg">
+ yaml::Node *Root = DI->getRoot();<br class="gmail_msg">
+ failIf(!Root, "expecting root node: " + InputFile);<br class="gmail_msg">
+ yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root);<br class="gmail_msg">
+ failIf(!Top, "expecting mapping node: " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto &KVNode : *Top) {<br class="gmail_msg">
+ auto Key = parseScalarString(KVNode.getKey());<br class="gmail_msg">
+<br class="gmail_msg">
+ if (Key == "covered-points") {<br class="gmail_msg">
+ yaml::SequenceNode *Points =<br class="gmail_msg">
+ dyn_cast<yaml::SequenceNode>(KVNode.getValue());<br class="gmail_msg">
+ failIf(!Points, "expected array: " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto I = Points->begin(), E = Points->end(); I != E; ++I) {<br class="gmail_msg">
+ Coverage->CoveredIds.insert(parseScalarString(&*I));<br class="gmail_msg">
+ }<br class="gmail_msg">
+ } else if (Key == "binary-hash") {<br class="gmail_msg">
+ Coverage->BinaryHash = parseScalarString(KVNode.getValue());<br class="gmail_msg">
+ } else if (Key == "point-symbol-info") {<br class="gmail_msg">
+ yaml::MappingNode *PointSymbolInfo =<br class="gmail_msg">
+ dyn_cast<yaml::MappingNode>(KVNode.getValue());<br class="gmail_msg">
+ failIf(!PointSymbolInfo, "expected mapping node: " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto &FileKVNode : *PointSymbolInfo) {<br class="gmail_msg">
+ auto Filename = parseScalarString(FileKVNode.getKey());<br class="gmail_msg">
+<br class="gmail_msg">
+ yaml::MappingNode *FileInfo =<br class="gmail_msg">
+ dyn_cast<yaml::MappingNode>(FileKVNode.getValue());<br class="gmail_msg">
+ failIf(!FileInfo, "expected mapping node: " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto &FunctionKVNode : *FileInfo) {<br class="gmail_msg">
+ auto FunctionName = parseScalarString(FunctionKVNode.getKey());<br class="gmail_msg">
+<br class="gmail_msg">
+ yaml::MappingNode *FunctionInfo =<br class="gmail_msg">
+ dyn_cast<yaml::MappingNode>(FunctionKVNode.getValue());<br class="gmail_msg">
+ failIf(!FunctionInfo, "expected mapping node: " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto &PointKVNode : *FunctionInfo) {<br class="gmail_msg">
+ auto PointId = parseScalarString(PointKVNode.getKey());<br class="gmail_msg">
+ auto Loc = parseScalarString(PointKVNode.getValue());<br class="gmail_msg">
+<br class="gmail_msg">
+ size_t ColonPos = Loc.find(':');<br class="gmail_msg">
+ failIf(ColonPos == std::string::npos, "expected ':': " + InputFile);<br class="gmail_msg">
+<br class="gmail_msg">
+ auto LineStr = Loc.substr(0, ColonPos);<br class="gmail_msg">
+ auto ColStr = Loc.substr(ColonPos + 1, Loc.size());<br class="gmail_msg">
+<br class="gmail_msg">
+ if (Points.find(PointId) == Points.end())<br class="gmail_msg">
+ Points.insert(std::make_pair(PointId, CoveragePoint(PointId)));<br class="gmail_msg">
+<br class="gmail_msg">
+ DILineInfo LineInfo;<br class="gmail_msg">
+ LineInfo.FileName = Filename;<br class="gmail_msg">
+ LineInfo.FunctionName = FunctionName;<br class="gmail_msg">
+ char *End;<br class="gmail_msg">
+ LineInfo.Line = std::strtoul(LineStr.c_str(), &End, 10);<br class="gmail_msg">
+ LineInfo.Column = std::strtoul(ColStr.c_str(), &End, 10);<br class="gmail_msg">
+<br class="gmail_msg">
+ CoveragePoint *CoveragePoint = &Points.find(PointId)->second;<br class="gmail_msg">
+ CoveragePoint->Locs.push_back(LineInfo);<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ } else {<br class="gmail_msg">
+ errs() << "Ignoring unknown key: " << Key << "\n";<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ for (auto &KV : Points) {<br class="gmail_msg">
+ Coverage->Points.push_back(KV.second);<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ return Coverage;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// ---------- MAIN FUNCTIONALITY ----------<br class="gmail_msg">
+<br class="gmail_msg">
std::string stripPathPrefix(std::string Path) {<br class="gmail_msg">
if (ClStripPathPrefix.empty())<br class="gmail_msg">
return Path;<br class="gmail_msg">
@@ -232,21 +561,11 @@ static std::unique_ptr<symbolize::LLVMSy<br class="gmail_msg">
new symbolize::LLVMSymbolizer(SymbolizerOptions));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-// A DILineInfo with address.<br class="gmail_msg">
-struct AddrInfo : public DILineInfo {<br class="gmail_msg">
- uint64_t Addr;<br class="gmail_msg">
-<br class="gmail_msg">
- AddrInfo(const DILineInfo &DI, uint64_t Addr) : DILineInfo(DI), Addr(Addr) {<br class="gmail_msg">
- FileName = normalizeFilename(FileName);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
-private:<br class="gmail_msg">
- static std::string normalizeFilename(const std::string &FileName) {<br class="gmail_msg">
- SmallString<256> S(FileName);<br class="gmail_msg">
- sys::path::remove_dots(S, /* remove_dot_dot */ true);<br class="gmail_msg">
- return S.str().str();<br class="gmail_msg">
- }<br class="gmail_msg">
-};<br class="gmail_msg">
+static std::string normalizeFilename(const std::string &FileName) {<br class="gmail_msg">
+ SmallString<256> S(FileName);<br class="gmail_msg">
+ sys::path::remove_dots(S, /* remove_dot_dot */ true);<br class="gmail_msg">
+ return stripPathPrefix(S.str().str());<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
class Blacklists {<br class="gmail_msg">
public:<br class="gmail_msg">
@@ -254,16 +573,14 @@ public:<br class="gmail_msg">
: DefaultBlacklist(createDefaultBlacklist()),<br class="gmail_msg">
UserBlacklist(createUserBlacklist()) {}<br class="gmail_msg">
<br class="gmail_msg">
- // AddrInfo contains normalized filename. It is important to check it rather<br class="gmail_msg">
- // than DILineInfo.<br class="gmail_msg">
- bool isBlacklisted(const AddrInfo &AI) {<br class="gmail_msg">
- if (DefaultBlacklist && DefaultBlacklist->inSection("fun", AI.FunctionName))<br class="gmail_msg">
+ bool isBlacklisted(const DILineInfo &I) {<br class="gmail_msg">
+ if (DefaultBlacklist && DefaultBlacklist->inSection("fun", I.FunctionName))<br class="gmail_msg">
return true;<br class="gmail_msg">
- if (DefaultBlacklist && DefaultBlacklist->inSection("src", AI.FileName))<br class="gmail_msg">
+ if (DefaultBlacklist && DefaultBlacklist->inSection("src", I.FileName))<br class="gmail_msg">
return true;<br class="gmail_msg">
- if (UserBlacklist && UserBlacklist->inSection("fun", AI.FunctionName))<br class="gmail_msg">
+ if (UserBlacklist && UserBlacklist->inSection("fun", I.FunctionName))<br class="gmail_msg">
return true;<br class="gmail_msg">
- if (UserBlacklist && UserBlacklist->inSection("src", AI.FileName))<br class="gmail_msg">
+ if (UserBlacklist && UserBlacklist->inSection("src", I.FileName))<br class="gmail_msg">
return true;<br class="gmail_msg">
return false;<br class="gmail_msg">
}<br class="gmail_msg">
@@ -276,7 +593,7 @@ private:<br class="gmail_msg">
MemoryBuffer::getMemBuffer(DefaultBlacklistStr);<br class="gmail_msg">
std::string Error;<br class="gmail_msg">
auto Blacklist = SpecialCaseList::create(MB.get(), Error);<br class="gmail_msg">
- FailIfNotEmpty(Error);<br class="gmail_msg">
+ failIfNotEmpty(Error);<br class="gmail_msg">
return Blacklist;<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
@@ -290,32 +607,43 @@ private:<br class="gmail_msg">
std::unique_ptr<SpecialCaseList> UserBlacklist;<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
-// Collect all debug info for given addresses.<br class="gmail_msg">
-static std::vector<AddrInfo> getAddrInfo(const std::string &ObjectFile,<br class="gmail_msg">
- const std::set<uint64_t> &Addrs,<br class="gmail_msg">
- bool InlinedCode) {<br class="gmail_msg">
- std::vector<AddrInfo> Result;<br class="gmail_msg">
+static std::vector<CoveragePoint><br class="gmail_msg">
+getCoveragePoints(const std::string &ObjectFile,<br class="gmail_msg">
+ const std::set<uint64_t> &Addrs, bool InlinedCode) {<br class="gmail_msg">
+ std::vector<CoveragePoint> Result;<br class="gmail_msg">
auto Symbolizer(createSymbolizer());<br class="gmail_msg">
Blacklists B;<br class="gmail_msg">
<br class="gmail_msg">
for (auto Addr : Addrs) {<br class="gmail_msg">
+ std::set<DILineInfo> Infos; // deduplicate debug info.<br class="gmail_msg">
+<br class="gmail_msg">
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr);<br class="gmail_msg">
- FailIfError(LineInfo);<br class="gmail_msg">
- auto LineAddrInfo = AddrInfo(*LineInfo, Addr);<br class="gmail_msg">
- if (B.isBlacklisted(LineAddrInfo))<br class="gmail_msg">
+ failIfError(LineInfo);<br class="gmail_msg">
+ LineInfo->FileName = normalizeFilename(LineInfo->FileName);<br class="gmail_msg">
+ if (B.isBlacklisted(*LineInfo))<br class="gmail_msg">
continue;<br class="gmail_msg">
- Result.push_back(LineAddrInfo);<br class="gmail_msg">
+<br class="gmail_msg">
+ auto Id = utohexstr(Addr, true);<br class="gmail_msg">
+ auto Point = CoveragePoint(Id);<br class="gmail_msg">
+ Infos.insert(*LineInfo);<br class="gmail_msg">
+ Point.Locs.push_back(*LineInfo);<br class="gmail_msg">
+<br class="gmail_msg">
if (InlinedCode) {<br class="gmail_msg">
auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr);<br class="gmail_msg">
- FailIfError(InliningInfo);<br class="gmail_msg">
+ failIfError(InliningInfo);<br class="gmail_msg">
for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) {<br class="gmail_msg">
auto FrameInfo = InliningInfo->getFrame(I);<br class="gmail_msg">
- auto FrameAddrInfo = AddrInfo(FrameInfo, Addr);<br class="gmail_msg">
- if (B.isBlacklisted(FrameAddrInfo))<br class="gmail_msg">
+ FrameInfo.FileName = normalizeFilename(FrameInfo.FileName);<br class="gmail_msg">
+ if (B.isBlacklisted(FrameInfo))<br class="gmail_msg">
continue;<br class="gmail_msg">
- Result.push_back(FrameAddrInfo);<br class="gmail_msg">
+ if (Infos.find(FrameInfo) == Infos.end()) {<br class="gmail_msg">
+ Infos.insert(FrameInfo);<br class="gmail_msg">
+ Point.Locs.push_back(FrameInfo);<br class="gmail_msg">
+ }<br class="gmail_msg">
}<br class="gmail_msg">
}<br class="gmail_msg">
+<br class="gmail_msg">
+ Result.push_back(Point);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
return Result;<br class="gmail_msg">
@@ -353,7 +681,7 @@ static void findMachOIndirectCovFunction<br class="gmail_msg">
if (IndirectSymbol < Symtab.nsyms) {<br class="gmail_msg">
object::SymbolRef Symbol = *(O.getSymbolByIndex(IndirectSymbol));<br class="gmail_msg">
Expected<StringRef> Name = Symbol.getName();<br class="gmail_msg">
- FailIfError(Name);<br class="gmail_msg">
+ failIfError(Name);<br class="gmail_msg">
if (isCoveragePointSymbol(Name.get())) {<br class="gmail_msg">
Result->insert(Addr);<br class="gmail_msg">
}<br class="gmail_msg">
@@ -376,11 +704,11 @@ findSanitizerCovFunctions(const object::<br class="gmail_msg">
<br class="gmail_msg">
for (const object::SymbolRef &Symbol : O.symbols()) {<br class="gmail_msg">
Expected<uint64_t> AddressOrErr = Symbol.getAddress();<br class="gmail_msg">
- FailIfError(AddressOrErr);<br class="gmail_msg">
+ failIfError(AddressOrErr);<br class="gmail_msg">
uint64_t Address = AddressOrErr.get();<br class="gmail_msg">
<br class="gmail_msg">
Expected<StringRef> NameOrErr = Symbol.getName();<br class="gmail_msg">
- FailIfError(NameOrErr);<br class="gmail_msg">
+ failIfError(NameOrErr);<br class="gmail_msg">
StringRef Name = NameOrErr.get();<br class="gmail_msg">
<br class="gmail_msg">
if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined) &&<br class="gmail_msg">
@@ -394,11 +722,11 @@ findSanitizerCovFunctions(const object::<br class="gmail_msg">
CO->export_directories()) {<br class="gmail_msg">
uint32_t RVA;<br class="gmail_msg">
std::error_code EC = Export.getExportRVA(RVA);<br class="gmail_msg">
- FailIfError(EC);<br class="gmail_msg">
+ failIfError(EC);<br class="gmail_msg">
<br class="gmail_msg">
StringRef Name;<br class="gmail_msg">
EC = Export.getSymbolName(Name);<br class="gmail_msg">
- FailIfError(EC);<br class="gmail_msg">
+ failIfError(EC);<br class="gmail_msg">
<br class="gmail_msg">
if (isCoveragePointSymbol(Name))<br class="gmail_msg">
Result.insert(CO->getImageBase() + RVA);<br class="gmail_msg">
@@ -423,36 +751,36 @@ static void getObjectCoveragePoints(cons<br class="gmail_msg">
<br class="gmail_msg">
std::string Error;<br class="gmail_msg">
const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);<br class="gmail_msg">
- FailIfNotEmpty(Error);<br class="gmail_msg">
+ failIfNotEmpty(Error);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCSubtargetInfo> STI(<br class="gmail_msg">
TheTarget->createMCSubtargetInfo(TripleName, "", ""));<br class="gmail_msg">
- FailIfEmpty(STI, "no subtarget info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(STI, "no subtarget info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCRegisterInfo> MRI(<br class="gmail_msg">
TheTarget->createMCRegInfo(TripleName));<br class="gmail_msg">
- FailIfEmpty(MRI, "no register info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(MRI, "no register info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCAsmInfo> AsmInfo(<br class="gmail_msg">
TheTarget->createMCAsmInfo(*MRI, TripleName));<br class="gmail_msg">
- FailIfEmpty(AsmInfo, "no asm info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(AsmInfo, "no asm info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);<br class="gmail_msg">
MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());<br class="gmail_msg">
std::unique_ptr<MCDisassembler> DisAsm(<br class="gmail_msg">
TheTarget->createMCDisassembler(*STI, Ctx));<br class="gmail_msg">
- FailIfEmpty(DisAsm, "no disassembler info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(DisAsm, "no disassembler info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());<br class="gmail_msg">
- FailIfEmpty(MII, "no instruction info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(MII, "no instruction info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
std::unique_ptr<const MCInstrAnalysis> MIA(<br class="gmail_msg">
TheTarget->createMCInstrAnalysis(MII.get()));<br class="gmail_msg">
- FailIfEmpty(MIA, "no instruction analysis info for target " + TripleName);<br class="gmail_msg">
+ failIfEmpty(MIA, "no instruction analysis info for target " + TripleName);<br class="gmail_msg">
<br class="gmail_msg">
auto SanCovAddrs = findSanitizerCovFunctions(O);<br class="gmail_msg">
if (SanCovAddrs.empty())<br class="gmail_msg">
- Fail("__sanitizer_cov* functions not found");<br class="gmail_msg">
+ fail("__sanitizer_cov* functions not found");<br class="gmail_msg">
<br class="gmail_msg">
for (object::SectionRef Section : O.sections()) {<br class="gmail_msg">
if (Section.isVirtual() || !Section.isText()) // llvm-objdump does the same.<br class="gmail_msg">
@@ -463,7 +791,7 @@ static void getObjectCoveragePoints(cons<br class="gmail_msg">
continue;<br class="gmail_msg">
<br class="gmail_msg">
StringRef BytesStr;<br class="gmail_msg">
- FailIfError(Section.getContents(BytesStr));<br class="gmail_msg">
+ failIfError(Section.getContents(BytesStr));<br class="gmail_msg">
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),<br class="gmail_msg">
BytesStr.size());<br class="gmail_msg">
<br class="gmail_msg">
@@ -494,13 +822,13 @@ visitObjectFiles(const object::Archive &<br class="gmail_msg">
Error Err;<br class="gmail_msg">
for (auto &C : A.children(Err)) {<br class="gmail_msg">
Expected<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary();<br class="gmail_msg">
- FailIfError(ChildOrErr);<br class="gmail_msg">
+ failIfError(ChildOrErr);<br class="gmail_msg">
if (auto *O = dyn_cast<object::ObjectFile>(&*ChildOrErr.get()))<br class="gmail_msg">
Fn(*O);<br class="gmail_msg">
else<br class="gmail_msg">
- FailIfError(object::object_error::invalid_file_type);<br class="gmail_msg">
+ failIfError(object::object_error::invalid_file_type);<br class="gmail_msg">
}<br class="gmail_msg">
- FailIfError(std::move(Err));<br class="gmail_msg">
+ failIfError(std::move(Err));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
static void<br class="gmail_msg">
@@ -509,7 +837,7 @@ visitObjectFiles(const std::string &File<br class="gmail_msg">
Expected<object::OwningBinary<object::Binary>> BinaryOrErr =<br class="gmail_msg">
object::createBinary(FileName);<br class="gmail_msg">
if (!BinaryOrErr)<br class="gmail_msg">
- FailIfError(BinaryOrErr);<br class="gmail_msg">
+ failIfError(BinaryOrErr);<br class="gmail_msg">
<br class="gmail_msg">
object::Binary &Binary = *BinaryOrErr.get().getBinary();<br class="gmail_msg">
if (object::Archive *A = dyn_cast<object::Archive>(&Binary))<br class="gmail_msg">
@@ -517,10 +845,11 @@ visitObjectFiles(const std::string &File<br class="gmail_msg">
else if (object::ObjectFile *O = dyn_cast<object::ObjectFile>(&Binary))<br class="gmail_msg">
Fn(*O);<br class="gmail_msg">
else<br class="gmail_msg">
- FailIfError(object::object_error::invalid_file_type);<br class="gmail_msg">
+ failIfError(object::object_error::invalid_file_type);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-std::set<uint64_t> findSanitizerCovFunctions(const std::string &FileName) {<br class="gmail_msg">
+static std::set<uint64_t><br class="gmail_msg">
+findSanitizerCovFunctions(const std::string &FileName) {<br class="gmail_msg">
std::set<uint64_t> Result;<br class="gmail_msg">
visitObjectFiles(FileName, [&](const object::ObjectFile &O) {<br class="gmail_msg">
auto Addrs = findSanitizerCovFunctions(O);<br class="gmail_msg">
@@ -532,7 +861,7 @@ std::set<uint64_t> findSanitizerCovFunct<br class="gmail_msg">
// Locate addresses of all coverage points in a file. Coverage point<br class="gmail_msg">
// is defined as the 'address of instruction following __sanitizer_cov<br class="gmail_msg">
// call - 1'.<br class="gmail_msg">
-std::set<uint64_t> getCoveragePoints(const std::string &FileName) {<br class="gmail_msg">
+static std::set<uint64_t> findCoveragePointAddrs(const std::string &FileName) {<br class="gmail_msg">
std::set<uint64_t> Result;<br class="gmail_msg">
visitObjectFiles(FileName, [&](const object::ObjectFile &O) {<br class="gmail_msg">
getObjectCoveragePoints(O, &Result);<br class="gmail_msg">
@@ -541,66 +870,18 @@ std::set<uint64_t> getCoveragePoints(con<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
static void printCovPoints(const std::string &ObjFile, raw_ostream &OS) {<br class="gmail_msg">
- for (uint64_t Addr : getCoveragePoints(ObjFile)) {<br class="gmail_msg">
+ for (uint64_t Addr : findCoveragePointAddrs(ObjFile)) {<br class="gmail_msg">
OS << "0x";<br class="gmail_msg">
OS.write_hex(Addr);<br class="gmail_msg">
OS << "\n";<br class="gmail_msg">
}<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-static std::string escapeHtml(const std::string &S) {<br class="gmail_msg">
- std::string Result;<br class="gmail_msg">
- Result.reserve(S.size());<br class="gmail_msg">
- for (char Ch : S) {<br class="gmail_msg">
- switch (Ch) {<br class="gmail_msg">
- case '&':<br class="gmail_msg">
- Result.append("&");<br class="gmail_msg">
- break;<br class="gmail_msg">
- case '\'':<br class="gmail_msg">
- Result.append("'");<br class="gmail_msg">
- break;<br class="gmail_msg">
- case '"':<br class="gmail_msg">
- Result.append(""");<br class="gmail_msg">
- break;<br class="gmail_msg">
- case '<':<br class="gmail_msg">
- Result.append("<");<br class="gmail_msg">
- break;<br class="gmail_msg">
- case '>':<br class="gmail_msg">
- Result.append(">");<br class="gmail_msg">
- break;<br class="gmail_msg">
- default:<br class="gmail_msg">
- Result.push_back(Ch);<br class="gmail_msg">
- break;<br class="gmail_msg">
- }<br class="gmail_msg">
- }<br class="gmail_msg">
- return Result;<br class="gmail_msg">
-}<br class="gmail_msg">
-<br class="gmail_msg">
-// Adds leading zeroes wrapped in 'lz' style.<br class="gmail_msg">
-// Leading zeroes help locate 000% coverage.<br class="gmail_msg">
-static std::string formatHtmlPct(size_t Pct) {<br class="gmail_msg">
- Pct = std::max(std::size_t{0}, std::min(std::size_t{100}, Pct));<br class="gmail_msg">
-<br class="gmail_msg">
- std::string Num = std::to_string(Pct);<br class="gmail_msg">
- std::string Zeroes(3 - Num.size(), '0');<br class="gmail_msg">
- if (!Zeroes.empty())<br class="gmail_msg">
- Zeroes = "<span class='lz'>" + Zeroes + "</span>";<br class="gmail_msg">
-<br class="gmail_msg">
- return Zeroes + Num;<br class="gmail_msg">
-}<br class="gmail_msg">
-<br class="gmail_msg">
-static std::string anchorName(const std::string &Anchor) {<br class="gmail_msg">
- llvm::MD5 Hasher;<br class="gmail_msg">
- llvm::MD5::MD5Result Hash;<br class="gmail_msg">
- Hasher.update(Anchor);<br class="gmail_msg">
- Hasher.final(Hash);<br class="gmail_msg">
-<br class="gmail_msg">
- SmallString<32> HexString;<br class="gmail_msg">
- llvm::MD5::stringifyResult(Hash, HexString);<br class="gmail_msg">
- return HexString.str().str();<br class="gmail_msg">
-}<br class="gmail_msg">
-<br class="gmail_msg">
static ErrorOr<bool> isCoverageFile(const std::string &FileName) {<br class="gmail_msg">
+ auto ShortFileName = llvm::sys::path::filename(FileName);<br class="gmail_msg">
+ if (!SancovFileRegex.match(ShortFileName))<br class="gmail_msg">
+ return false;<br class="gmail_msg">
+<br class="gmail_msg">
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =<br class="gmail_msg">
MemoryBuffer::getFile(FileName);<br class="gmail_msg">
if (!BufOrErr) {<br class="gmail_msg">
@@ -618,490 +899,187 @@ static ErrorOr<bool> isCoverageFile(cons<br class="gmail_msg">
return Header->Magic == BinCoverageMagic;<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-struct CoverageStats {<br class="gmail_msg">
- CoverageStats() : AllPoints(0), CovPoints(0), AllFns(0), CovFns(0) {}<br class="gmail_msg">
-<br class="gmail_msg">
- size_t AllPoints;<br class="gmail_msg">
- size_t CovPoints;<br class="gmail_msg">
- size_t AllFns;<br class="gmail_msg">
- size_t CovFns;<br class="gmail_msg">
-};<br class="gmail_msg">
-<br class="gmail_msg">
-static raw_ostream &operator<<(raw_ostream &OS, const CoverageStats &Stats) {<br class="gmail_msg">
- OS << "all-edges: " << Stats.AllPoints << "\n";<br class="gmail_msg">
- OS << "cov-edges: " << Stats.CovPoints << "\n";<br class="gmail_msg">
- OS << "all-functions: " << Stats.AllFns << "\n";<br class="gmail_msg">
- OS << "cov-functions: " << Stats.CovFns << "\n";<br class="gmail_msg">
- return OS;<br class="gmail_msg">
+static bool isSymbolizedCoverageFile(const std::string &FileName) {<br class="gmail_msg">
+ auto ShortFileName = llvm::sys::path::filename(FileName);<br class="gmail_msg">
+ return SymcovFileRegex.match(ShortFileName);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-class CoverageData {<br class="gmail_msg">
-public:<br class="gmail_msg">
- // Read single file coverage data.<br class="gmail_msg">
- static ErrorOr<std::unique_ptr<CoverageData>><br class="gmail_msg">
- read(const std::string &FileName) {<br class="gmail_msg">
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =<br class="gmail_msg">
- MemoryBuffer::getFile(FileName);<br class="gmail_msg">
- if (!BufOrErr)<br class="gmail_msg">
- return BufOrErr.getError();<br class="gmail_msg">
- std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());<br class="gmail_msg">
- if (Buf->getBufferSize() < 8) {<br class="gmail_msg">
- errs() << "File too small (<8): " << Buf->getBufferSize() << '\n';<br class="gmail_msg">
- return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
- }<br class="gmail_msg">
- const FileHeader *Header =<br class="gmail_msg">
- reinterpret_cast<const FileHeader *>(Buf->getBufferStart());<br class="gmail_msg">
-<br class="gmail_msg">
- if (Header->Magic != BinCoverageMagic) {<br class="gmail_msg">
- errs() << "Wrong magic: " << Header->Magic << '\n';<br class="gmail_msg">
- return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- auto Addrs = llvm::make_unique<std::set<uint64_t>>();<br class="gmail_msg">
-<br class="gmail_msg">
- switch (Header->Bitness) {<br class="gmail_msg">
- case Bitness64:<br class="gmail_msg">
- readInts<uint64_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),<br class="gmail_msg">
- Addrs.get());<br class="gmail_msg">
- break;<br class="gmail_msg">
- case Bitness32:<br class="gmail_msg">
- readInts<uint32_t>(Buf->getBufferStart() + 8, Buf->getBufferEnd(),<br class="gmail_msg">
- Addrs.get());<br class="gmail_msg">
- break;<br class="gmail_msg">
- default:<br class="gmail_msg">
- errs() << "Unsupported bitness: " << Header->Bitness << '\n';<br class="gmail_msg">
- return make_error_code(errc::illegal_byte_sequence);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- // Merge multiple coverage data together.<br class="gmail_msg">
- static std::unique_ptr<CoverageData><br class="gmail_msg">
- merge(const std::vector<std::unique_ptr<CoverageData>> &Covs) {<br class="gmail_msg">
- auto Addrs = llvm::make_unique<std::set<uint64_t>>();<br class="gmail_msg">
-<br class="gmail_msg">
- for (const auto &Cov : Covs)<br class="gmail_msg">
- Addrs->insert(Cov->Addrs->begin(), Cov->Addrs->end());<br class="gmail_msg">
-<br class="gmail_msg">
- return std::unique_ptr<CoverageData>(new CoverageData(std::move(Addrs)));<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- // Read list of files and merges their coverage info.<br class="gmail_msg">
- static ErrorOr<std::unique_ptr<CoverageData>><br class="gmail_msg">
- readAndMerge(const std::vector<std::string> &FileNames) {<br class="gmail_msg">
- std::vector<std::unique_ptr<CoverageData>> Covs;<br class="gmail_msg">
- for (const auto &FileName : FileNames) {<br class="gmail_msg">
- auto Cov = read(FileName);<br class="gmail_msg">
- if (!Cov)<br class="gmail_msg">
- return Cov.getError();<br class="gmail_msg">
- Covs.push_back(std::move(Cov.get()));<br class="gmail_msg">
- }<br class="gmail_msg">
- return merge(Covs);<br class="gmail_msg">
- }<br class="gmail_msg">
+static std::unique_ptr<SymbolizedCoverage><br class="gmail_msg">
+symbolize(const RawCoverage &Data, const std::string ObjectFile) {<br class="gmail_msg">
+ auto Coverage = make_unique<SymbolizedCoverage>();<br class="gmail_msg">
<br class="gmail_msg">
- // Print coverage addresses.<br class="gmail_msg">
- void printAddrs(raw_ostream &OS) {<br class="gmail_msg">
- for (auto Addr : *Addrs) {<br class="gmail_msg">
- OS << "0x";<br class="gmail_msg">
- OS.write_hex(Addr);<br class="gmail_msg">
- OS << "\n";<br class="gmail_msg">
- }<br class="gmail_msg">
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =<br class="gmail_msg">
+ MemoryBuffer::getFile(ObjectFile);<br class="gmail_msg">
+ failIfError(BufOrErr);<br class="gmail_msg">
+ SHA1 Hasher;<br class="gmail_msg">
+ Hasher.update((*BufOrErr)->getBuffer());<br class="gmail_msg">
+ Coverage->BinaryHash = toHex(Hasher.final());<br class="gmail_msg">
+<br class="gmail_msg">
+ for (uint64_t Addr : *Data.Addrs) {<br class="gmail_msg">
+ Coverage->CoveredIds.insert(utohexstr(Addr, true));<br class="gmail_msg">
+ }<br class="gmail_msg">
+<br class="gmail_msg">
+ std::set<uint64_t> AllAddrs = findCoveragePointAddrs(ObjectFile);<br class="gmail_msg">
+ if (!std::includes(AllAddrs.begin(), AllAddrs.end(), Data.Addrs->begin(),<br class="gmail_msg">
+ Data.Addrs->end())) {<br class="gmail_msg">
+ fail("Coverage points in binary and .sancov file do not match.");<br class="gmail_msg">
}<br class="gmail_msg">
+ Coverage->Points = getCoveragePoints(ObjectFile, AllAddrs, true);<br class="gmail_msg">
+ return Coverage;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
-protected:<br class="gmail_msg">
- explicit CoverageData(std::unique_ptr<std::set<uint64_t>> Addrs)<br class="gmail_msg">
- : Addrs(std::move(Addrs)) {}<br class="gmail_msg">
-<br class="gmail_msg">
- friend class CoverageDataWithObjectFile;<br class="gmail_msg">
+struct FileFn {<br class="gmail_msg">
+ bool operator<(const FileFn &RHS) const {<br class="gmail_msg">
+ return std::tie(FileName, FunctionName) <<br class="gmail_msg">
+ std::tie(RHS.FileName, RHS.FunctionName);<br class="gmail_msg">
+ }<br class="gmail_msg">
<br class="gmail_msg">
- std::unique_ptr<std::set<uint64_t>> Addrs;<br class="gmail_msg">
+ std::string FileName;<br class="gmail_msg">
+ std::string FunctionName;<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
-// Coverage data translated into source code line-level information.<br class="gmail_msg">
-// Fetches debug info in constructor and calculates various information per<br class="gmail_msg">
-// request.<br class="gmail_msg">
-class SourceCoverageData {<br class="gmail_msg">
-public:<br class="gmail_msg">
- enum LineStatus {<br class="gmail_msg">
- // coverage information for the line is not available.<br class="gmail_msg">
- // default value in maps.<br class="gmail_msg">
- UNKNOWN = 0,<br class="gmail_msg">
- // the line is fully covered.<br class="gmail_msg">
- COVERED = 1,<br class="gmail_msg">
- // the line is fully uncovered.<br class="gmail_msg">
- NOT_COVERED = 2,<br class="gmail_msg">
- // some points in the line a covered, some are not.<br class="gmail_msg">
- MIXED = 3<br class="gmail_msg">
- };<br class="gmail_msg">
-<br class="gmail_msg">
- SourceCoverageData(std::string ObjectFile, const std::set<uint64_t> &Addrs)<br class="gmail_msg">
- : AllCovPoints(getCoveragePoints(ObjectFile)) {<br class="gmail_msg">
- if (!std::includes(AllCovPoints.begin(), AllCovPoints.end(), Addrs.begin(),<br class="gmail_msg">
- Addrs.end())) {<br class="gmail_msg">
- Fail("Coverage points in binary and .sancov file do not match.");<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- AllAddrInfo = getAddrInfo(ObjectFile, AllCovPoints, true);<br class="gmail_msg">
- CovAddrInfo = getAddrInfo(ObjectFile, Addrs, true);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- // Compute number of coverage points hit/total in a file.<br class="gmail_msg">
- // file_name -> <coverage, all_coverage><br class="gmail_msg">
- std::map<std::string, std::pair<size_t, size_t>> computeFileCoverage() {<br class="gmail_msg">
- std::map<std::string, std::pair<size_t, size_t>> FileCoverage;<br class="gmail_msg">
- auto AllCovPointsByFile =<br class="gmail_msg">
- group_by(AllAddrInfo, [](const AddrInfo &AI) { return AI.FileName; });<br class="gmail_msg">
- auto CovPointsByFile =<br class="gmail_msg">
- group_by(CovAddrInfo, [](const AddrInfo &AI) { return AI.FileName; });<br class="gmail_msg">
-<br class="gmail_msg">
- for (const auto &P : AllCovPointsByFile) {<br class="gmail_msg">
- const std::string &FileName = P.first;<br class="gmail_msg">
-<br class="gmail_msg">
- FileCoverage[FileName] =<br class="gmail_msg">
- std::make_pair(CovPointsByFile[FileName].size(),<br class="gmail_msg">
- AllCovPointsByFile[FileName].size());<br class="gmail_msg">
- }<br class="gmail_msg">
- return FileCoverage;<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- // line_number -> line_status.<br class="gmail_msg">
- typedef std::map<int, LineStatus> LineStatusMap;<br class="gmail_msg">
- // file_name -> LineStatusMap<br class="gmail_msg">
- typedef std::map<std::string, LineStatusMap> FileLineStatusMap;<br class="gmail_msg">
-<br class="gmail_msg">
- // fills in the {file_name -> {line_no -> status}} map.<br class="gmail_msg">
- FileLineStatusMap computeLineStatusMap() {<br class="gmail_msg">
- FileLineStatusMap StatusMap;<br class="gmail_msg">
-<br class="gmail_msg">
- auto AllLocs = group_by(AllAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileLoc{AI.FileName, AI.Line};<br class="gmail_msg">
- });<br class="gmail_msg">
- auto CovLocs = group_by(CovAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileLoc{AI.FileName, AI.Line};<br class="gmail_msg">
- });<br class="gmail_msg">
-<br class="gmail_msg">
- for (const auto &P : AllLocs) {<br class="gmail_msg">
- const FileLoc &Loc = P.first;<br class="gmail_msg">
- auto I = CovLocs.find(Loc);<br class="gmail_msg">
-<br class="gmail_msg">
- if (I == CovLocs.end()) {<br class="gmail_msg">
- StatusMap[Loc.FileName][Loc.Line] = NOT_COVERED;<br class="gmail_msg">
- } else {<br class="gmail_msg">
- StatusMap[Loc.FileName][Loc.Line] =<br class="gmail_msg">
- (I->second.size() == P.second.size()) ? COVERED : MIXED;<br class="gmail_msg">
- }<br class="gmail_msg">
+static std::set<FileFn><br class="gmail_msg">
+computeFunctions(const std::vector<CoveragePoint> &Points) {<br class="gmail_msg">
+ std::set<FileFn> Fns;<br class="gmail_msg">
+ for (const auto &Point : Points) {<br class="gmail_msg">
+ for (const auto &Loc : Point.Locs) {<br class="gmail_msg">
+ Fns.insert(FileFn{Loc.FileName, Loc.FunctionName});<br class="gmail_msg">
}<br class="gmail_msg">
- return StatusMap;<br class="gmail_msg">
}<br class="gmail_msg">
+ return Fns;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
- std::set<FileFn> computeAllFunctions() const {<br class="gmail_msg">
- std::set<FileFn> Fns;<br class="gmail_msg">
- for (const auto &AI : AllAddrInfo) {<br class="gmail_msg">
- Fns.insert(FileFn{AI.FileName, AI.FunctionName});<br class="gmail_msg">
- }<br class="gmail_msg">
- return Fns;<br class="gmail_msg">
- }<br class="gmail_msg">
+static std::set<FileFn><br class="gmail_msg">
+computeNotCoveredFunctions(const SymbolizedCoverage &Coverage) {<br class="gmail_msg">
+ auto Fns = computeFunctions(Coverage.Points);<br class="gmail_msg">
<br class="gmail_msg">
- std::set<FileFn> computeCoveredFunctions() const {<br class="gmail_msg">
- std::set<FileFn> Fns;<br class="gmail_msg">
- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileFn{AI.FileName, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
+ for (const auto &Point : Coverage.Points) {<br class="gmail_msg">
+ if (Coverage.CoveredIds.find(Point.Id) == Coverage.CoveredIds.end())<br class="gmail_msg">
+ continue;<br class="gmail_msg">
<br class="gmail_msg">
- for (const auto &P : CovFns) {<br class="gmail_msg">
- Fns.insert(P.first);<br class="gmail_msg">
+ for (const auto &Loc : Point.Locs) {<br class="gmail_msg">
+ Fns.erase(FileFn{Loc.FileName, Loc.FunctionName});<br class="gmail_msg">
}<br class="gmail_msg">
- return Fns;<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
- std::set<FileFn> computeNotCoveredFunctions() const {<br class="gmail_msg">
- std::set<FileFn> Fns;<br class="gmail_msg">
-<br class="gmail_msg">
- auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileFn{AI.FileName, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileFn{AI.FileName, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
-<br class="gmail_msg">
- for (const auto &P : AllFns) {<br class="gmail_msg">
- if (CovFns.find(P.first) == CovFns.end()) {<br class="gmail_msg">
- Fns.insert(P.first);<br class="gmail_msg">
- }<br class="gmail_msg">
- }<br class="gmail_msg">
- return Fns;<br class="gmail_msg">
- }<br class="gmail_msg">
+ return Fns;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
- // Compute % coverage for each function.<br class="gmail_msg">
- std::map<FileFn, int> computeFunctionsCoverage() const {<br class="gmail_msg">
- std::map<FileFn, int> FnCoverage;<br class="gmail_msg">
- auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileFn{AI.FileName, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
+static std::set<FileFn><br class="gmail_msg">
+computeCoveredFunctions(const SymbolizedCoverage &Coverage) {<br class="gmail_msg">
+ auto AllFns = computeFunctions(Coverage.Points);<br class="gmail_msg">
+ std::set<FileFn> Result;<br class="gmail_msg">
<br class="gmail_msg">
- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FileFn{AI.FileName, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
+ for (const auto &Point : Coverage.Points) {<br class="gmail_msg">
+ if (Coverage.CoveredIds.find(Point.Id) == Coverage.CoveredIds.end())<br class="gmail_msg">
+ continue;<br class="gmail_msg">
<br class="gmail_msg">
- for (const auto &P : AllFns) {<br class="gmail_msg">
- FileFn F = P.first;<br class="gmail_msg">
- FnCoverage[F] = CovFns[F].size() * 100 / P.second.size();<br class="gmail_msg">
+ for (const auto &Loc : Point.Locs) {<br class="gmail_msg">
+ Result.insert(FileFn{Loc.FileName, Loc.FunctionName});<br class="gmail_msg">
}<br class="gmail_msg">
-<br class="gmail_msg">
- return FnCoverage;<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
- typedef std::map<FileLoc, std::set<std::string>> FunctionLocs;<br class="gmail_msg">
- // finds first line number in a file for each function.<br class="gmail_msg">
- FunctionLocs resolveFunctions(const std::set<FileFn> &Fns) const {<br class="gmail_msg">
- std::vector<AddrInfo> FnAddrs;<br class="gmail_msg">
- for (const auto &AI : AllAddrInfo) {<br class="gmail_msg">
- if (Fns.find(FileFn{AI.FileName, AI.FunctionName}) != Fns.end())<br class="gmail_msg">
- FnAddrs.push_back(AI);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- auto GroupedAddrs = group_by(FnAddrs, [](const AddrInfo &AI) {<br class="gmail_msg">
- return FnLoc{FileLoc{AI.FileName, AI.Line}, AI.FunctionName};<br class="gmail_msg">
- });<br class="gmail_msg">
-<br class="gmail_msg">
- FunctionLocs Result;<br class="gmail_msg">
- std::string LastFileName;<br class="gmail_msg">
- std::set<std::string> ProcessedFunctions;<br class="gmail_msg">
-<br class="gmail_msg">
- for (const auto &P : GroupedAddrs) {<br class="gmail_msg">
- const FnLoc &Loc = P.first;<br class="gmail_msg">
- std::string FileName = Loc.Loc.FileName;<br class="gmail_msg">
- std::string FunctionName = Loc.FunctionName;<br class="gmail_msg">
-<br class="gmail_msg">
- if (LastFileName != FileName)<br class="gmail_msg">
- ProcessedFunctions.clear();<br class="gmail_msg">
- LastFileName = FileName;<br class="gmail_msg">
+ return Result;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
- if (!ProcessedFunctions.insert(FunctionName).second)<br class="gmail_msg">
+typedef std::map<FileFn, std::pair<uint32_t, uint32_t>> FunctionLocs;<br class="gmail_msg">
+// finds first location in a file for each function.<br class="gmail_msg">
+static FunctionLocs resolveFunctions(const SymbolizedCoverage &Coverage,<br class="gmail_msg">
+ const std::set<FileFn> &Fns) {<br class="gmail_msg">
+ FunctionLocs Result;<br class="gmail_msg">
+ for (const auto &Point : Coverage.Points) {<br class="gmail_msg">
+ for (const auto &Loc : Point.Locs) {<br class="gmail_msg">
+ FileFn Fn = FileFn{Loc.FileName, Loc.FunctionName};<br class="gmail_msg">
+ if (Fns.find(Fn) == Fns.end())<br class="gmail_msg">
continue;<br class="gmail_msg">
<br class="gmail_msg">
- auto FLoc = FileLoc{FileName, Loc.Loc.Line};<br class="gmail_msg">
- Result[FLoc].insert(FunctionName);<br class="gmail_msg">
- }<br class="gmail_msg">
- return Result;<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- std::set<std::string> files() const {<br class="gmail_msg">
- std::set<std::string> Files;<br class="gmail_msg">
- for (const auto &AI : AllAddrInfo) {<br class="gmail_msg">
- Files.insert(AI.FileName);<br class="gmail_msg">
+ auto P = std::make_pair(Loc.Line, Loc.Column);<br class="gmail_msg">
+ auto I = Result.find(Fn);<br class="gmail_msg">
+ if (I == Result.end() || I->second > P) {<br class="gmail_msg">
+ Result[Fn] = P;<br class="gmail_msg">
+ }<br class="gmail_msg">
}<br class="gmail_msg">
- return Files;<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- void collectStats(CoverageStats *Stats) const {<br class="gmail_msg">
- Stats->AllPoints += AllCovPoints.size();<br class="gmail_msg">
- Stats->AllFns += computeAllFunctions().size();<br class="gmail_msg">
- Stats->CovFns += computeCoveredFunctions().size();<br class="gmail_msg">
}<br class="gmail_msg">
+ return Result;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
-private:<br class="gmail_msg">
- const std::set<uint64_t> AllCovPoints;<br class="gmail_msg">
-<br class="gmail_msg">
- std::vector<AddrInfo> AllAddrInfo;<br class="gmail_msg">
- std::vector<AddrInfo> CovAddrInfo;<br class="gmail_msg">
-};<br class="gmail_msg">
-<br class="gmail_msg">
-static void printFunctionLocs(const SourceCoverageData::FunctionLocs &FnLocs,<br class="gmail_msg">
- raw_ostream &OS) {<br class="gmail_msg">
- for (const auto &Fns : FnLocs) {<br class="gmail_msg">
- for (const auto &Fn : Fns.second) {<br class="gmail_msg">
- OS << stripPathPrefix(Fns.first.FileName) << ":" << Fns.first.Line << " "<br class="gmail_msg">
- << Fn << "\n";<br class="gmail_msg">
- }<br class="gmail_msg">
+static void printFunctionLocs(const FunctionLocs &FnLocs, raw_ostream &OS) {<br class="gmail_msg">
+ for (const auto &P : FnLocs) {<br class="gmail_msg">
+ OS << stripPathPrefix(P.first.FileName) << ":" << P.second.first << " "<br class="gmail_msg">
+ << P.first.FunctionName << "\n";<br class="gmail_msg">
+ }<br class="gmail_msg">
+}<br class="gmail_msg">
+CoverageStats computeStats(const SymbolizedCoverage &Coverage) {<br class="gmail_msg">
+ CoverageStats Stats = {Coverage.Points.size(), Coverage.CoveredIds.size(),<br class="gmail_msg">
+ computeFunctions(Coverage.Points).size(),<br class="gmail_msg">
+ computeCoveredFunctions(Coverage).size()};<br class="gmail_msg">
+ return Stats;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// Print list of covered functions.<br class="gmail_msg">
+// Line format: <file_name>:<line> <function_name><br class="gmail_msg">
+static void printCoveredFunctions(const SymbolizedCoverage &CovData,<br class="gmail_msg">
+ raw_ostream &OS) {<br class="gmail_msg">
+ auto CoveredFns = computeCoveredFunctions(CovData);<br class="gmail_msg">
+ printFunctionLocs(resolveFunctions(CovData, CoveredFns), OS);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// Print list of not covered functions.<br class="gmail_msg">
+// Line format: <file_name>:<line> <function_name><br class="gmail_msg">
+static void printNotCoveredFunctions(const SymbolizedCoverage &CovData,<br class="gmail_msg">
+ raw_ostream &OS) {<br class="gmail_msg">
+ auto NotCoveredFns = computeNotCoveredFunctions(CovData);<br class="gmail_msg">
+ printFunctionLocs(resolveFunctions(CovData, NotCoveredFns), OS);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// Read list of files and merges their coverage info.<br class="gmail_msg">
+static void readAndPrintRawCoverage(const std::vector<std::string> &FileNames,<br class="gmail_msg">
+ raw_ostream &OS) {<br class="gmail_msg">
+ std::vector<std::unique_ptr<RawCoverage>> Covs;<br class="gmail_msg">
+ for (const auto &FileName : FileNames) {<br class="gmail_msg">
+ auto Cov = RawCoverage::read(FileName);<br class="gmail_msg">
+ if (!Cov)<br class="gmail_msg">
+ continue;<br class="gmail_msg">
+ OS << *Cov.get();<br class="gmail_msg">
}<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-// Holder for coverage data + filename of corresponding object file.<br class="gmail_msg">
-class CoverageDataWithObjectFile : public CoverageData {<br class="gmail_msg">
-public:<br class="gmail_msg">
- static ErrorOr<std::unique_ptr<CoverageDataWithObjectFile>><br class="gmail_msg">
- readAndMerge(const std::string &ObjectFile,<br class="gmail_msg">
- const std::vector<std::string> &FileNames) {<br class="gmail_msg">
- auto MergedDataOrError = CoverageData::readAndMerge(FileNames);<br class="gmail_msg">
- if (!MergedDataOrError)<br class="gmail_msg">
- return MergedDataOrError.getError();<br class="gmail_msg">
- return std::unique_ptr<CoverageDataWithObjectFile>(<br class="gmail_msg">
- new CoverageDataWithObjectFile(ObjectFile,<br class="gmail_msg">
- std::move(MergedDataOrError.get())));<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- std::string object_file() const { return ObjectFile; }<br class="gmail_msg">
-<br class="gmail_msg">
- // Print list of covered functions.<br class="gmail_msg">
- // Line format: <file_name>:<line> <function_name><br class="gmail_msg">
- void printCoveredFunctions(raw_ostream &OS) const {<br class="gmail_msg">
- SourceCoverageData SCovData(ObjectFile, *Addrs);<br class="gmail_msg">
- auto CoveredFns = SCovData.computeCoveredFunctions();<br class="gmail_msg">
- printFunctionLocs(SCovData.resolveFunctions(CoveredFns), OS);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- // Print list of not covered functions.<br class="gmail_msg">
- // Line format: <file_name>:<line> <function_name><br class="gmail_msg">
- void printNotCoveredFunctions(raw_ostream &OS) const {<br class="gmail_msg">
- SourceCoverageData SCovData(ObjectFile, *Addrs);<br class="gmail_msg">
- auto NotCoveredFns = SCovData.computeNotCoveredFunctions();<br class="gmail_msg">
- printFunctionLocs(SCovData.resolveFunctions(NotCoveredFns), OS);<br class="gmail_msg">
- }<br class="gmail_msg">
-<br class="gmail_msg">
- void printReport(raw_ostream &OS) const {<br class="gmail_msg">
- SourceCoverageData SCovData(ObjectFile, *Addrs);<br class="gmail_msg">
- auto LineStatusMap = SCovData.computeLineStatusMap();<br class="gmail_msg">
-<br class="gmail_msg">
- std::set<FileFn> AllFns = SCovData.computeAllFunctions();<br class="gmail_msg">
- // file_loc -> set[function_name]<br class="gmail_msg">
- auto AllFnsByLoc = SCovData.resolveFunctions(AllFns);<br class="gmail_msg">
- auto FileCoverage = SCovData.computeFileCoverage();<br class="gmail_msg">
-<br class="gmail_msg">
- auto FnCoverage = SCovData.computeFunctionsCoverage();<br class="gmail_msg">
- auto FnCoverageByFile =<br class="gmail_msg">
- group_by(FnCoverage, [](const std::pair<FileFn, int> &FileFn) {<br class="gmail_msg">
- return FileFn.first.FileName;<br class="gmail_msg">
- });<br class="gmail_msg">
-<br class="gmail_msg">
- // TOC<br class="gmail_msg">
-<br class="gmail_msg">
- size_t NotCoveredFilesCount = 0;<br class="gmail_msg">
- std::set<std::string> Files = SCovData.files();<br class="gmail_msg">
-<br class="gmail_msg">
- // Covered Files.<br class="gmail_msg">
- OS << "<details open><summary>Touched Files</summary>\n";<br class="gmail_msg">
- OS << "<table>\n";<br class="gmail_msg">
- OS << "<tr><th>File</th><th>Coverage %</th>";<br class="gmail_msg">
- OS << "<th>Hit (Total) Fns</th></tr>\n";<br class="gmail_msg">
- for (const auto &FileName : Files) {<br class="gmail_msg">
- std::pair<size_t, size_t> FC = FileCoverage[FileName];<br class="gmail_msg">
- if (FC.first == 0) {<br class="gmail_msg">
- NotCoveredFilesCount++;<br class="gmail_msg">
- continue;<br class="gmail_msg">
- }<br class="gmail_msg">
- size_t CovPct = FC.second == 0 ? 100 : 100 * FC.first / FC.second;<br class="gmail_msg">
+static std::unique_ptr<SymbolizedCoverage><br class="gmail_msg">
+merge(const std::vector<std::unique_ptr<SymbolizedCoverage>> &Coverages) {<br class="gmail_msg">
+ auto Result = make_unique<SymbolizedCoverage>();<br class="gmail_msg">
<br class="gmail_msg">
- </blockquote></div></blockquote></div>