@@ -100,6 +100,11 @@ void VirtualUnwinder::unwindLinear(UnwindState &State, uint64_t Repeat) {
100
100
InstructionPointer &IP = State.InstPtr ;
101
101
uint64_t Target = State.getCurrentLBRTarget ();
102
102
uint64_t End = IP.Address ;
103
+ if (Target > End) {
104
+ // Skip unwinding the rest of LBR trace when a bogus range is seen.
105
+ State.setInvalid ();
106
+ return ;
107
+ }
103
108
if (Binary->usePseudoProbes ()) {
104
109
// We don't need to top frame probe since it should be extracted
105
110
// from the range.
@@ -303,19 +308,28 @@ bool VirtualUnwinder::unwind(const PerfSample *Sample, uint64_t Repeat) {
303
308
// extra frame when processing the return paired with this call.
304
309
unwindCall (State);
305
310
} else if (isReturnState (State)) {
306
- // Unwind returns - check whether the IP is indeed at a return instruction
311
+ // Unwind returns - check whether the IP is indeed at a return
312
+ // instruction
307
313
unwindReturn (State);
308
- } else {
314
+ } else if ( isValidState (State)) {
309
315
// Unwind branches
310
- // For regular intra function branches, we only need to record branch with
311
- // context. For an artificial branch cross function boundaries, we got an
312
- // issue with returning to external code. Take the two LBR enties for
313
- // example: [foo:8(RETURN), ext:1] [ext:3(CALL), bar:1] After perf reader,
314
- // we only get[foo:8(RETURN), bar:1], unwinder will be confused like foo
315
- // return to bar. Here we detect and treat this case as BRANCH instead of
316
- // RETURN which only update the source address.
316
+ // For regular intra function branches, we only need to record branch
317
+ // with context. For an artificial branch cross function boundaries, we
318
+ // got an issue with returning to external code. Take the two LBR enties
319
+ // for example: [foo:8(RETURN), ext:1] [ext:3(CALL), bar:1] After perf
320
+ // reader, we only get[foo:8(RETURN), bar:1], unwinder will be confused
321
+ // like foo return to bar. Here we detect and treat this case as BRANCH
322
+ // instead of RETURN which only update the source address.
317
323
unwindBranch (State);
324
+ } else {
325
+ // Skip unwinding the rest of LBR trace. Reset the stack and update the
326
+ // state so that the rest of the trace can still be processed as if they
327
+ // do not have stack samples.
328
+ State.clearCallStack ();
329
+ State.InstPtr .update (State.getCurrentLBRSource ());
330
+ State.pushFrame (State.InstPtr .Address );
318
331
}
332
+
319
333
State.advanceLBR ();
320
334
// Record `branch` with calling context after unwinding.
321
335
recordBranchCount (Branch, State, Repeat);
@@ -720,7 +734,9 @@ void HybridPerfReader::parseSample(TraceStream &TraceIt, uint64_t Count) {
720
734
// ... 0x4005c8/0x4005dc/P/-/-/0 # LBR Entries
721
735
//
722
736
std::shared_ptr<PerfSample> Sample = std::make_shared<PerfSample>();
723
-
737
+ #ifndef NDEBUG
738
+ Sample->Linenum = TraceIt.getLineNumber ();
739
+ #endif
724
740
// Parsing call stack and populate into PerfSample.CallStack
725
741
if (!extractCallstack (TraceIt, Sample->CallStack )) {
726
742
// Skip the next LBR line matched current call stack
@@ -915,8 +931,10 @@ void PerfScriptReader::computeCounterFromLBR(const PerfSample *Sample,
915
931
// If this not the first LBR, update the range count between TO of current
916
932
// LBR and FROM of next LBR.
917
933
uint64_t StartOffset = TargetOffset;
918
- if (EndOffeset != 0 )
919
- Counter.recordRangeCount (StartOffset, EndOffeset, Repeat);
934
+ if (EndOffeset != 0 ) {
935
+ if (StartOffset <= EndOffeset)
936
+ Counter.recordRangeCount (StartOffset, EndOffeset, Repeat);
937
+ }
920
938
EndOffeset = SourceOffset;
921
939
}
922
940
}
@@ -1161,41 +1179,55 @@ void PerfScriptReader::warnInvalidRange() {
1161
1179
const char *RangeCrossFuncMsg =
1162
1180
" Fall through range should not cross function boundaries, likely due to "
1163
1181
" profile and binary mismatch." ;
1182
+ const char *BogusRangeMsg = " Range start is after range end." ;
1164
1183
1184
+ uint64_t TotalRangeNum = 0 ;
1165
1185
uint64_t InstNotBoundary = 0 ;
1166
1186
uint64_t UnmatchedRange = 0 ;
1167
1187
uint64_t RangeCrossFunc = 0 ;
1188
+ uint64_t BogusRange = 0 ;
1168
1189
1169
1190
for (auto &I : Ranges) {
1170
1191
uint64_t StartOffset = I.first .first ;
1171
1192
uint64_t EndOffset = I.first .second ;
1193
+ TotalRangeNum += I.second ;
1172
1194
1173
1195
if (!Binary->offsetIsCode (StartOffset) ||
1174
1196
!Binary->offsetIsTransfer (EndOffset)) {
1175
- InstNotBoundary++ ;
1197
+ InstNotBoundary += I. second ;
1176
1198
WarnInvalidRange (StartOffset, EndOffset, EndNotBoundaryMsg);
1177
1199
}
1178
1200
1179
1201
auto *FRange = Binary->findFuncRangeForOffset (StartOffset);
1180
1202
if (!FRange) {
1181
- UnmatchedRange++ ;
1203
+ UnmatchedRange += I. second ;
1182
1204
WarnInvalidRange (StartOffset, EndOffset, DanglingRangeMsg);
1183
1205
continue ;
1184
1206
}
1185
1207
1186
1208
if (EndOffset >= FRange->EndOffset ) {
1187
- RangeCrossFunc++ ;
1209
+ RangeCrossFunc += I. second ;
1188
1210
WarnInvalidRange (StartOffset, EndOffset, RangeCrossFuncMsg);
1189
1211
}
1212
+
1213
+ if (StartOffset > EndOffset) {
1214
+ BogusRange += I.second ;
1215
+ WarnInvalidRange (StartOffset, EndOffset, BogusRangeMsg);
1216
+ }
1190
1217
}
1191
1218
1192
- uint64_t TotalRangeNum = Ranges.size ();
1193
- emitWarningSummary (InstNotBoundary, TotalRangeNum,
1194
- " of profiled ranges are not on instruction boundary." );
1195
- emitWarningSummary (UnmatchedRange, TotalRangeNum,
1196
- " of profiled ranges do not belong to any functions." );
1197
- emitWarningSummary (RangeCrossFunc, TotalRangeNum,
1198
- " of profiled ranges do cross function boundaries." );
1219
+ emitWarningSummary (
1220
+ InstNotBoundary, TotalRangeNum,
1221
+ " of samples are from ranges that are not on instruction boundary." );
1222
+ emitWarningSummary (
1223
+ UnmatchedRange, TotalRangeNum,
1224
+ " of samples are from ranges that do not belong to any functions." );
1225
+ emitWarningSummary (
1226
+ RangeCrossFunc, TotalRangeNum,
1227
+ " of samples are from ranges that do cross function boundaries." );
1228
+ emitWarningSummary (
1229
+ BogusRange, TotalRangeNum,
1230
+ " of samples are from ranges that have range start after range end." );
1199
1231
}
1200
1232
1201
1233
void PerfScriptReader::parsePerfTraces () {
0 commit comments