[Profile] PE binary coverage bug fix

PR/32584

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

llvm-svn: 300277
This commit is contained in:
Xinliang David Li 2017-04-13 23:37:12 +00:00
parent 83409b8174
commit 96faeb6322
10 changed files with 195 additions and 59 deletions

View 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_"; }

View 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)

View 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);

View 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;

View 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;

View 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;

View 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);
}

View 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;
}

View 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

View 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;