]> granicus.if.org Git - llvm/commitdiff
[Profile] PE binary coverage bug fix
authorXinliang David Li <davidxl@google.com>
Thu, 13 Apr 2017 23:37:12 +0000 (23:37 +0000)
committerXinliang David Li <davidxl@google.com>
Thu, 13 Apr 2017 23:37:12 +0000 (23:37 +0000)
PR/32584

Differential Revision: https://reviews.llvm.org/D32023

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300277 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ProfileData/InstrProf.h
include/llvm/ProfileData/InstrProfData.inc
include/llvm/Transforms/InstrProfiling.h
lib/CodeGen/TargetLoweringObjectFileImpl.cpp
lib/ProfileData/Coverage/CoverageMappingReader.cpp
lib/ProfileData/InstrProf.cpp
lib/Transforms/Instrumentation/InstrProfiling.cpp
lib/Transforms/Instrumentation/ThreadSanitizer.cpp
test/Instrumentation/InstrProfiling/PR23499.ll
tools/llvm-cov/TestingSupport.cpp

index f97bbfd9e0d8ee7b95d21b05ca5a14fdb81eca5e..6e9e0af1db75ad484db7c45c7f65b49f5987f7c2 100644 (file)
@@ -54,39 +54,29 @@ class MDNode;
 class Module;
 
 /// Return the name of data section containing profile counter variables.
-inline StringRef getInstrProfCountersSectionName(bool AddSegment) {
-  return AddSegment ? "__DATA," INSTR_PROF_CNTS_SECT_NAME_STR
-                    : INSTR_PROF_CNTS_SECT_NAME_STR;
-}
+/// If M is null, the target platform is assumed to be the same as
+/// the host machine, and the segment prefix will not be added.
+std::string getInstrProfCountersSectionName(const Module *M = nullptr);
 
 /// Return the name of data section containing names of instrumented
-/// functions.
-inline StringRef getInstrProfNameSectionName(bool AddSegment) {
-  return AddSegment ? "__DATA," INSTR_PROF_NAME_SECT_NAME_STR
-                    : INSTR_PROF_NAME_SECT_NAME_STR;
-}
+/// functions. If M is null, the target platform is assumed to be the same as
+/// the host machine, nor will segment prefix be added.
+std::string getInstrProfNameSectionName(const Module *M = nullptr);
 
 /// Return the name of the data section containing per-function control
-/// data.
-inline StringRef getInstrProfDataSectionName(bool AddSegment) {
-  return AddSegment ? "__DATA," INSTR_PROF_DATA_SECT_NAME_STR
-                      ",regular,live_support"
-                    : INSTR_PROF_DATA_SECT_NAME_STR;
-}
+/// data. If M is null, the target platform is assumed to be the same as
+/// the host machine, and the segment prefix will not be added.
+std::string getInstrProfDataSectionName(const Module *M = nullptr);
 
 /// Return the name of data section containing pointers to value profile
-/// counters/nodes.
-inline StringRef getInstrProfValuesSectionName(bool AddSegment) {
-  return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR
-                    : INSTR_PROF_VALS_SECT_NAME_STR;
-}
+/// counters/nodes. If M is null, the target platform is assumed to be
+/// the same as the host machine, and the segment prefix will not be added.
+std::string getInstrProfValuesSectionName(const Module *M = nullptr);
 
 /// Return the name of data section containing nodes holdling value
-/// profiling data.
-inline StringRef getInstrProfVNodesSectionName(bool AddSegment) {
-  return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR
-                    : INSTR_PROF_VNODES_SECT_NAME_STR;
-}
+/// profiling data. If M is null, the target platform is assumed to be
+/// the same as the host machine, and the segment prefix will not be added.
+std::string getInstrProfVNodesSectionName(const Module *M = nullptr);
 
 /// Return the name profile runtime entry point to do value profiling
 /// for a given site.
@@ -101,10 +91,7 @@ inline StringRef getInstrProfValueRangeProfFuncName() {
 
 /// Return the name of the section containing function coverage mapping
 /// data.
-inline StringRef getInstrProfCoverageSectionName(bool AddSegment) {
-  return AddSegment ? "__LLVM_COV," INSTR_PROF_COVMAP_SECT_NAME_STR
-                    : INSTR_PROF_COVMAP_SECT_NAME_STR;
-}
+std::string getInstrProfCoverageSectionName(const Module *M = nullptr);
 
 /// Return the name prefix of variables containing instrumented function names.
 inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; }
index 6ef1625d81c42d094e1456adb81a872498a56bad..949a50c0b3f9680ae0a0e276dda9ebf66a81d8cc 100644 (file)
@@ -246,6 +246,31 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
 /* COVMAP_HEADER end.  */
 
 
+#ifdef INSTR_PROF_SECT_ENTRY
+#define INSTR_PROF_DATA_DEFINED
+INSTR_PROF_SECT_ENTRY(IPSK_data, INSTR_PROF_DATA_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_cnts, INSTR_PROF_CNTS_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_name, INSTR_PROF_NAME_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vals, INSTR_PROF_VALS_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vnodes, INSTR_PROF_VNODES_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_covmap, INSTR_PROF_COVMAP_SECT_NAME_STR, \
+                      INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
+                      INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,")
+
+#undef INSTR_PROF_SECT_ENTRY
+#endif
+
+
 #ifdef INSTR_PROF_VALUE_PROF_DATA
 #define INSTR_PROF_DATA_DEFINED
 
@@ -622,17 +647,47 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
  * specified via command line. */
 #define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename
 
+/* section name strings common to all targets other
+   than WIN32 */
+#define INSTR_PROF_DATA_COMMON __llvm_prf_data
+#define INSTR_PROF_NAME_COMMON __llvm_prf_names
+#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
+#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
+#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
+#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
+/* Win32 */
+#define INSTR_PROF_DATA_COFF .lprfd
+#define INSTR_PROF_NAME_COFF .lprfn
+#define INSTR_PROF_CNTS_COFF .lprfc
+#define INSTR_PROF_VALS_COFF .lprfv
+#define INSTR_PROF_VNODES_COFF .lprfnd
+#define INSTR_PROF_COVMAP_COFF .lcovmap
+
+#ifdef _WIN32
 /* Runtime section names and name strings.  */
-#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
-#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
-#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
 /* Array of pointers. Each pointer points to a list
  * of value nodes associated with one value site.
  */
-#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF
 /* Value profile nodes section. */
-#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds
-#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
+#else
+/* Runtime section names and name strings.  */
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON
+#endif
 
 #define INSTR_PROF_DATA_SECT_NAME_STR                                          \
   INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME)
index e303dcf7acfef1794d4fd4bd82690f875d432ac2..6f2286f32ecfa58db887321718d86375f3e0c058 100644 (file)
@@ -67,16 +67,16 @@ private:
   bool isMachO() const;
 
   /// Get the section name for the counter variables.
-  StringRef getCountersSection() const;
+  std::string getCountersSection() const;
 
   /// Get the section name for the name variables.
-  StringRef getNameSection() const;
+  std::string getNameSection() const;
 
   /// Get the section name for the profile data variables.
-  StringRef getDataSection() const;
+  std::string getDataSection() const;
 
   /// Get the section name for the coverage mapping data.
-  StringRef getCoverageSection() const;
+  std::string getCoverageSection() const;
 
   /// Count the number of instrumented value sites for the function.
   void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins);
index 78afeda67dbf2dcd4e7e39b7b19254c26fa48373..2de5d1b780edfee13fc0ad58acf756e5e13126ff 100644 (file)
@@ -133,7 +133,9 @@ getELFKindForNamedSection(StringRef Name, SectionKind K) {
   //
   //   .section   .eh_frame,"a",@progbits
   
-  if (Name == getInstrProfCoverageSectionName(false))
+  // TODO: to support Win->ELF cross compilation with coverage properly,
+  // need to pass the module pointer to the following call.
+  if (Name == getInstrProfCoverageSectionName())
     return SectionKind::getMetadata();
 
   if (Name.empty() || Name[0] != '.') return K;
index 05c5b28d7a0765d7e90a2ff52a9f1ce0eef3e271..515f19a3b4067b67f543dc62a820036c0406a6d6 100644 (file)
@@ -648,11 +648,15 @@ static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
                                 : support::endianness::big;
 
   // Look for the sections that we are interested in.
-  auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false));
+  // TODO: with the current getInstrProfXXXSectionName interfaces, the
+  // the coverage reader host tool is limited to read coverage section on
+  // binaries with compatible profile section naming scheme as the host
+  // platform. Currently, COFF format binaries have different section
+  // naming scheme from the all the rest.
+  auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName());
   if (auto E = NamesSection.takeError())
     return E;
-  auto CoverageSection =
-      lookupSection(*OF, getInstrProfCoverageSectionName(false));
+  auto CoverageSection = lookupSection(*OF, getInstrProfCoverageSectionName());
   if (auto E = CoverageSection.takeError())
     return E;
 
index 0ec3fce4b2377da275fea8959ab7cacb730841af..d66d25eb190c1240e1fa577aa1121bf5151e2502 100644 (file)
@@ -136,8 +136,92 @@ const std::error_category &llvm::instrprof_category() {
   return *ErrorCategory;
 }
 
+namespace {
+
+enum InstrProfSectKind {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff,    \
+                              Prefix)                                          \
+  Kind,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+const char *InstrProfSectName[] = {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff,    \
+                              Prefix)                                          \
+  SectName,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+const char *InstrProfSectNameCommon[] = {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff,    \
+                              Prefix)                                          \
+  SectNameCommon,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+const char *InstrProfSectNameCoff[] = {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff,    \
+                              Prefix)                                          \
+  SectNameCoff,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+const char *InstrProfSectNamePrefix[] = {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff,    \
+                              Prefix)                                          \
+  Prefix,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+std::string getInstrProfSectionName(const Module *M, InstrProfSectKind Kind) {
+
+  if (!M)
+    return InstrProfSectName[Kind];
+
+  bool AddSegment = Triple(M->getTargetTriple()).isOSBinFormatMachO();
+  std::string SectName;
+  if (Triple(M->getTargetTriple()).isOSBinFormatCOFF())
+    SectName = InstrProfSectNameCoff[Kind];
+  else
+    SectName = InstrProfSectNameCommon[Kind];
+
+  if (AddSegment) {
+    SectName = InstrProfSectNamePrefix[Kind] + SectName;
+    if (Kind == IPSK_data) {
+      SectName += ",regular,live_support";
+    }
+  }
+  return SectName;
+}
+
+} // namespace
+
 namespace llvm {
 
+std::string getInstrProfCountersSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_cnts);
+}
+
+std::string getInstrProfNameSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_name);
+}
+
+std::string getInstrProfDataSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_data);
+}
+
+std::string getInstrProfValuesSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_vals);
+}
+
+std::string getInstrProfVNodesSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_vnodes);
+}
+
+std::string getInstrProfCoverageSectionName(const Module *M) {
+  return getInstrProfSectionName(M, IPSK_covmap);
+}
+
 void SoftInstrProfErrors::addError(instrprof_error IE) {
   if (IE == instrprof_error::success)
     return;
index 1f8bcb9a330ea1e3f32f4e9142f5e9bf17cc7096..c47467f1a84cb7f5bd485cc78977290ea5705b84 100644 (file)
@@ -145,23 +145,23 @@ bool InstrProfiling::isMachO() const {
 }
 
 /// Get the section name for the counter variables.
-StringRef InstrProfiling::getCountersSection() const {
-  return getInstrProfCountersSectionName(isMachO());
+std::string InstrProfiling::getCountersSection() const {
+  return getInstrProfCountersSectionName(M);
 }
 
 /// Get the section name for the name variables.
-StringRef InstrProfiling::getNameSection() const {
-  return getInstrProfNameSectionName(isMachO());
+std::string InstrProfiling::getNameSection() const {
+  return getInstrProfNameSectionName(M);
 }
 
 /// Get the section name for the profile data variables.
-StringRef InstrProfiling::getDataSection() const {
-  return getInstrProfDataSectionName(isMachO());
+std::string InstrProfiling::getDataSection() const {
+  return getInstrProfDataSectionName(M);
 }
 
 /// Get the section name for the coverage mapping data.
-StringRef InstrProfiling::getCoverageSection() const {
-  return getInstrProfCoverageSectionName(isMachO());
+std::string InstrProfiling::getCoverageSection() const {
+  return getInstrProfCoverageSectionName(M);
 }
 
 static InstrProfIncrementInst *castToIncrementInst(Instruction *Instr) {
@@ -462,7 +462,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
                              Constant::getNullValue(ValuesTy),
                              getVarName(Inc, getInstrProfValuesVarPrefix()));
       ValuesVar->setVisibility(NamePtr->getVisibility());
-      ValuesVar->setSection(getInstrProfValuesSectionName(isMachO()));
+      ValuesVar->setSection(getInstrProfValuesSectionName(M));
       ValuesVar->setAlignment(8);
       ValuesVar->setComdat(ProfileVarsComdat);
       ValuesPtrExpr =
@@ -557,7 +557,7 @@ void InstrProfiling::emitVNodes() {
   auto *VNodesVar = new GlobalVariable(
       *M, VNodesTy, false, GlobalValue::PrivateLinkage,
       Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
-  VNodesVar->setSection(getInstrProfVNodesSectionName(isMachO()));
+  VNodesVar->setSection(getInstrProfVNodesSectionName(M));
   UsedVars.push_back(VNodesVar);
 }
 
index 2ec6d09594dee4207d966858b7c1a3a06d2c5e94..c6a6f954d13d774a6f56c15cd0461ece87676df8 100644 (file)
@@ -280,8 +280,7 @@ static bool shouldInstrumentReadWriteFromAddress(Value *Addr) {
     if (GV->hasSection()) {
       StringRef SectionName = GV->getSection();
       // Check if the global is in the PGO counters section.
-      if (SectionName.endswith(getInstrProfCountersSectionName(
-            /*AddSegment=*/false)))
+      if (SectionName.endswith(getInstrProfCountersSectionName()))
         return false;
     }
 
index 8c4ef3712d0617f2435b7e46d38c7a55daa6c1e6..101fad19950e6c75a2992ad445581bbd7fceed6e 100644 (file)
@@ -20,8 +20,8 @@ $_Z3barIvEvv = comdat any
 
 
 ; COFF-NOT: __profn__Z3barIvEvv
-; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat, align 8
-; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data{{.*}}", comdat($__profc__Z3barIvEvv), align 8
+; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}prfc", comdat, align 8
+; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($__profc__Z3barIvEvv), align 8
 
 
 declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1
index 72768f4fd583fc81970216cb6bd43b99258db122..a272aa5422e071ff69bdcc34c4a71faced4f67f3 100644 (file)
@@ -52,9 +52,14 @@ int convertForTestingMain(int argc, const char *argv[]) {
     StringRef Name;
     if (Section.getName(Name))
       return 1;
-    if (Name == llvm::getInstrProfNameSectionName(false)) {
+    // TODO: with the current getInstrProfXXXSectionName interfaces, the
+    // the  host tool is limited to read coverage section on
+    // binaries with compatible profile section naming scheme as the host
+    // platform. Currently, COFF format binaries have different section
+    // naming scheme from the all the rest.
+    if (Name == llvm::getInstrProfNameSectionName()) {
       ProfileNames = Section;
-    } else if (Name == llvm::getInstrProfCoverageSectionName(false)) {
+    } else if (Name == llvm::getInstrProfCoverageSectionName()) {
       CoverageMapping = Section;
     } else
       continue;