]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
perf intel-pt: Fix "Unexpected indirect branch" error
[linux.git] / tools / perf / util / intel-pt-decoder / intel-pt-decoder.c
index 881d7c5e5e2a3c8114eaccb9524c16f7494482aa..d404bed7003aacee1079af492ba3f20334edc06e 100644 (file)
@@ -113,6 +113,7 @@ struct intel_pt_decoder {
        bool have_cyc;
        bool fixup_last_mtc;
        bool have_last_ip;
+       enum intel_pt_param_flags flags;
        uint64_t pos;
        uint64_t last_ip;
        uint64_t ip;
@@ -226,6 +227,8 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
        decoder->return_compression = params->return_compression;
        decoder->branch_enable      = params->branch_enable;
 
+       decoder->flags              = params->flags;
+
        decoder->period             = params->period;
        decoder->period_type        = params->period_type;
 
@@ -1097,6 +1100,15 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
        return ret;
 }
 
+static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder,
+                                         struct intel_pt_insn *intel_pt_insn,
+                                         uint64_t ip, int err)
+{
+       return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err &&
+              intel_pt_insn->branch == INTEL_PT_BR_INDIRECT &&
+              ip == decoder->ip + intel_pt_insn->length;
+}
+
 static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
 {
        struct intel_pt_insn intel_pt_insn;
@@ -1109,10 +1121,11 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
                err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip);
                if (err == INTEL_PT_RETURN)
                        return 0;
-               if (err == -EAGAIN) {
+               if (err == -EAGAIN ||
+                   intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) {
                        if (intel_pt_fup_event(decoder))
                                return 0;
-                       return err;
+                       return -EAGAIN;
                }
                decoder->set_fup_tx_flags = false;
                if (err)