Skip to content

Commit ee88b8d

Browse files
committed
[compiler-rt] Add more diagnostic to InstrProfError
If profile data is malformed for any kind of reason, we generate an error that only reports "malformed instrumentation profile data" without any further information. This patch extends InstrProfError class to receive an optional error message argument, so that we can do better error reporting. Differential Revision: https://reviews.llvm.org/D108942
1 parent 1e78d5d commit ee88b8d

9 files changed

+241
-60
lines changed

llvm/include/llvm/ProfileData/InstrProf.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ inline std::error_code make_error_code(instrprof_error E) {
308308

309309
class InstrProfError : public ErrorInfo<InstrProfError> {
310310
public:
311-
InstrProfError(instrprof_error Err) : Err(Err) {
311+
InstrProfError(instrprof_error Err, const Twine &ErrStr = Twine())
312+
: Err(Err), Msg(ErrStr.str()) {
312313
assert(Err != instrprof_error::success && "Not an error");
313314
}
314315

@@ -321,6 +322,7 @@ class InstrProfError : public ErrorInfo<InstrProfError> {
321322
}
322323

323324
instrprof_error get() const { return Err; }
325+
const std::string &getMessage() const { return Msg; }
324326

325327
/// Consume an Error and return the raw enum value contained within it. The
326328
/// Error must either be a success value, or contain a single InstrProfError.
@@ -337,6 +339,7 @@ class InstrProfError : public ErrorInfo<InstrProfError> {
337339

338340
private:
339341
instrprof_error Err;
342+
std::string Msg;
340343
};
341344

342345
class SoftInstrProfErrors {
@@ -474,7 +477,8 @@ class InstrProfSymtab {
474477
/// is used by the raw and text profile readers.
475478
Error addFuncName(StringRef FuncName) {
476479
if (FuncName.empty())
477-
return make_error<InstrProfError>(instrprof_error::malformed);
480+
return make_error<InstrProfError>(instrprof_error::malformed,
481+
"function name is empty");
478482
auto Ins = NameTab.insert(FuncName);
479483
if (Ins.second) {
480484
MD5NameMap.push_back(std::make_pair(

llvm/include/llvm/ProfileData/InstrProfReader.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class InstrProfIterator {
7171
/// format. Provides an iterator over NamedInstrProfRecords.
7272
class InstrProfReader {
7373
instrprof_error LastError = instrprof_error::success;
74+
std::string LastErrorMsg;
7475

7576
public:
7677
InstrProfReader() = default;
@@ -114,14 +115,21 @@ class InstrProfReader {
114115
std::unique_ptr<InstrProfSymtab> Symtab;
115116

116117
/// Set the current error and return same.
117-
Error error(instrprof_error Err) {
118+
Error error(instrprof_error Err, const std::string &ErrMsg = "") {
118119
LastError = Err;
120+
LastErrorMsg = ErrMsg;
119121
if (Err == instrprof_error::success)
120122
return Error::success();
121-
return make_error<InstrProfError>(Err);
123+
return make_error<InstrProfError>(Err, ErrMsg);
122124
}
123125

124-
Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
126+
Error error(Error &&E) {
127+
handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
128+
LastError = IPE.get();
129+
LastErrorMsg = IPE.getMessage();
130+
});
131+
return make_error<InstrProfError>(LastError, LastErrorMsg);
132+
}
125133

126134
/// Clear the current error and return a successful one.
127135
Error success() { return error(instrprof_error::success); }
@@ -136,7 +144,7 @@ class InstrProfReader {
136144
/// Get the current error.
137145
Error getError() {
138146
if (hasError())
139-
return make_error<InstrProfError>(LastError);
147+
return make_error<InstrProfError>(LastError, LastErrorMsg);
140148
return Error::success();
141149
}
142150

llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,8 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
567567
if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
568568
return Err;
569569
if (FuncName.empty())
570-
return make_error<InstrProfError>(instrprof_error::malformed);
570+
return make_error<InstrProfError>(instrprof_error::malformed,
571+
"function name is empty");
571572
++CovMapNumUsedRecords;
572573
Records.emplace_back(Version, FuncName, FuncHash, Mapping,
573574
FileRange.StartingIndex, FileRange.Length);

llvm/lib/ProfileData/InstrProf.cpp

+68-31
Original file line numberDiff line numberDiff line change
@@ -74,53 +74,85 @@ static cl::opt<unsigned> StaticFuncStripDirNamePrefix(
7474
cl::desc("Strip specified level of directory name from source path in "
7575
"the profile counter name for static functions."));
7676

77-
static std::string getInstrProfErrString(instrprof_error Err) {
77+
static std::string getInstrProfErrString(instrprof_error Err,
78+
const std::string &ErrMsg = "") {
79+
std::string Msg;
80+
raw_string_ostream OS(Msg);
81+
7882
switch (Err) {
7983
case instrprof_error::success:
80-
return "success";
84+
OS << "success";
85+
break;
8186
case instrprof_error::eof:
82-
return "end of File";
87+
OS << "end of File";
88+
break;
8389
case instrprof_error::unrecognized_format:
84-
return "unrecognized instrumentation profile encoding format";
90+
OS << "unrecognized instrumentation profile encoding format";
91+
break;
8592
case instrprof_error::bad_magic:
86-
return "invalid instrumentation profile data (bad magic)";
93+
OS << "invalid instrumentation profile data (bad magic)";
94+
break;
8795
case instrprof_error::bad_header:
88-
return "invalid instrumentation profile data (file header is corrupt)";
96+
OS << "invalid instrumentation profile data (file header is corrupt)";
97+
break;
8998
case instrprof_error::unsupported_version:
90-
return "unsupported instrumentation profile format version";
99+
OS << "unsupported instrumentation profile format version";
100+
break;
91101
case instrprof_error::unsupported_hash_type:
92-
return "unsupported instrumentation profile hash type";
102+
OS << "unsupported instrumentation profile hash type";
103+
break;
93104
case instrprof_error::too_large:
94-
return "too much profile data";
105+
OS << "too much profile data";
106+
break;
95107
case instrprof_error::truncated:
96-
return "truncated profile data";
108+
OS << "truncated profile data";
109+
break;
97110
case instrprof_error::malformed:
98-
return "malformed instrumentation profile data";
111+
OS << "malformed instrumentation profile data";
112+
break;
99113
case instrprof_error::invalid_prof:
100-
return "invalid profile created. Please file a bug "
101-
"at: " BUG_REPORT_URL
102-
" and include the profraw files that caused this error.";
114+
OS << "invalid profile created. Please file a bug "
115+
"at: " BUG_REPORT_URL
116+
" and include the profraw files that caused this error.";
117+
break;
103118
case instrprof_error::unknown_function:
104-
return "no profile data available for function";
119+
OS << "no profile data available for function";
120+
break;
105121
case instrprof_error::hash_mismatch:
106-
return "function control flow change detected (hash mismatch)";
122+
OS << "function control flow change detected (hash mismatch)";
123+
break;
107124
case instrprof_error::count_mismatch:
108-
return "function basic block count change detected (counter mismatch)";
125+
OS << "function basic block count change detected (counter mismatch)";
126+
break;
109127
case instrprof_error::counter_overflow:
110-
return "counter overflow";
128+
OS << "counter overflow";
129+
break;
111130
case instrprof_error::value_site_count_mismatch:
112-
return "function value site count change detected (counter mismatch)";
131+
OS << "function value site count change detected (counter mismatch)";
132+
break;
113133
case instrprof_error::compress_failed:
114-
return "failed to compress data (zlib)";
134+
OS << "failed to compress data (zlib)";
135+
break;
115136
case instrprof_error::uncompress_failed:
116-
return "failed to uncompress data (zlib)";
137+
OS << "failed to uncompress data (zlib)";
138+
break;
117139
case instrprof_error::empty_raw_profile:
118-
return "empty raw profile file";
140+
OS << "empty raw profile file";
141+
break;
119142
case instrprof_error::zlib_unavailable:
120-
return "profile uses zlib compression but the profile reader was built "
121-
"without zlib support";
143+
OS << "profile uses zlib compression but the profile reader was built "
144+
"without zlib support";
145+
break;
146+
default:
147+
llvm_unreachable("A value of instrprof_error has no message.");
148+
break;
122149
}
123-
llvm_unreachable("A value of instrprof_error has no message.");
150+
151+
// If optional error message is not empty, append it to the message.
152+
if (!ErrMsg.empty())
153+
OS << ": '" << ErrMsg << "'";
154+
155+
return OS.str();
124156
}
125157

126158
namespace {
@@ -217,7 +249,7 @@ void SoftInstrProfErrors::addError(instrprof_error IE) {
217249
}
218250

219251
std::string InstrProfError::message() const {
220-
return getInstrProfErrString(Err);
252+
return getInstrProfErrString(Err, Msg);
221253
}
222254

223255
char InstrProfError::ID = 0;
@@ -878,18 +910,23 @@ static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
878910

879911
Error ValueProfData::checkIntegrity() {
880912
if (NumValueKinds > IPVK_Last + 1)
881-
return make_error<InstrProfError>(instrprof_error::malformed);
882-
// Total size needs to be mulltiple of quadword size.
913+
return make_error<InstrProfError>(
914+
instrprof_error::malformed, "number of value profile kinds is invalid");
915+
// Total size needs to be multiple of quadword size.
883916
if (TotalSize % sizeof(uint64_t))
884-
return make_error<InstrProfError>(instrprof_error::malformed);
917+
return make_error<InstrProfError>(
918+
instrprof_error::malformed, "total size is not multiples of quardword");
885919

886920
ValueProfRecord *VR = getFirstValueProfRecord(this);
887921
for (uint32_t K = 0; K < this->NumValueKinds; K++) {
888922
if (VR->Kind > IPVK_Last)
889-
return make_error<InstrProfError>(instrprof_error::malformed);
923+
return make_error<InstrProfError>(instrprof_error::malformed,
924+
"value kind is invalid");
890925
VR = getValueProfRecordNext(VR);
891926
if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
892-
return make_error<InstrProfError>(instrprof_error::malformed);
927+
return make_error<InstrProfError>(
928+
instrprof_error::malformed,
929+
"value profile address is greater than total size");
893930
}
894931
return Error::success();
895932
}

0 commit comments

Comments
 (0)