Skip to content

Commit 60dc2df

Browse files
ptxed, test: resync-on-error
Add a ptxed option --resync-on-error to use pt_blk_resync() or pt_insn_resync() for re-synchronizing onto the trace stream after a decode error. Signed-off-by: Markus Metzger <[email protected]>
1 parent 4e82a88 commit 60dc2df

18 files changed

+1406
-38
lines changed

ptxed/src/ptxed.c

Lines changed: 148 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ struct ptxed_options {
151151
/* Print sideband warnings. */
152152
uint32_t print_sb_warnings:1;
153153
#endif
154+
155+
#if (LIBIPT_VERSION >= 0x202)
156+
/* Resync on error. */
157+
uint32_t resync_on_error:1;
158+
#endif
154159
};
155160

156161
/* A collection of flags selecting which stats to collect/print. */
@@ -248,6 +253,9 @@ static void help(const char *name)
248253
printf(" --time print the current timestamp.\n");
249254
printf(" --raw-insn print the raw bytes of each instruction.\n");
250255
printf(" --check perform checks (expensive).\n");
256+
#if (LIBIPT_VERSION >= 0x202)
257+
printf(" --resync-on-error resync on decode errors more aggressively.\n");
258+
#endif
251259
printf(" --iscache-limit <size> set the image section cache limit to <size> bytes.\n");
252260
printf(" --event:time print the tsc for events if available.\n");
253261
printf(" --event:ip print the ip of events if available.\n");
@@ -1532,6 +1540,36 @@ static int drain_events_insn(struct ptxed_decoder *decoder, uint64_t *time,
15321540
return status;
15331541
}
15341542

1543+
#if (LIBIPT_VERSION >= 0x202)
1544+
static int resync_insn(struct ptxed_decoder *decoder,
1545+
const struct ptxed_options *options,
1546+
uint64_t *time)
1547+
{
1548+
int status;
1549+
1550+
if (!decoder || !options)
1551+
return -pte_internal;
1552+
1553+
for (;;) {
1554+
status = pt_insn_resync(decoder->variant.insn);
1555+
if (status >= 0)
1556+
break;
1557+
1558+
if (status != -pte_event_ignored)
1559+
return status;
1560+
1561+
status = handle_one_event_insn(decoder, options, time);
1562+
if (status < 0)
1563+
return status;
1564+
}
1565+
1566+
if ((status & pts_ip_suppressed) && !options->quiet)
1567+
printf("[disabled]\n");
1568+
1569+
return status;
1570+
}
1571+
#endif /* (LIBIPT_VERSION >= 0x202) */
1572+
15351573
static int decode_one_insn(struct ptxed_decoder *decoder,
15361574
const struct ptxed_options *options,
15371575
struct ptxed_stats *stats, struct pt_insn *insn,
@@ -1633,31 +1671,49 @@ static void decode_insn(struct ptxed_decoder *decoder,
16331671
}
16341672

16351673
for (;;) {
1636-
status = drain_events_insn(decoder, &time, status,
1637-
options);
1638-
if (status < 0)
1639-
break;
1674+
for (;;) {
1675+
status = drain_events_insn(decoder, &time,
1676+
status, options);
1677+
if (status < 0)
1678+
break;
1679+
1680+
if (status & pts_eos) {
1681+
if (!(status & pts_ip_suppressed) &&
1682+
!options->quiet)
1683+
printf("[end of trace]\n");
1684+
1685+
status = -pte_eos;
1686+
break;
1687+
}
1688+
1689+
status = decode_one_insn(decoder, options,
1690+
stats, &insn, time);
1691+
if (status < 0)
1692+
break;
1693+
}
1694+
1695+
/* We're done when we reach the end of the trace
1696+
* stream.
1697+
*/
1698+
if (status == -pte_eos)
1699+
return;
16401700

1641-
if (status & pts_eos) {
1642-
if (!(status & pts_ip_suppressed) &&
1643-
!options->quiet)
1644-
printf("[end of trace]\n");
1701+
diagnose_insn(decoder, "error", status, &insn);
16451702

1646-
status = -pte_eos;
1703+
#if (LIBIPT_VERSION >= 0x202)
1704+
if (!options->resync_on_error)
16471705
break;
1648-
}
16491706

1650-
status = decode_one_insn(decoder, options, stats,
1651-
&insn, time);
1652-
if (status < 0)
1707+
status = resync_insn(decoder, options, &time);
1708+
if (status < 0) {
1709+
diagnose_insn(decoder, "resync error", status,
1710+
&insn);
16531711
break;
1654-
}
1655-
1656-
/* We're done when we reach the end of the trace stream. */
1657-
if (status == -pte_eos)
1712+
}
1713+
#else
16581714
break;
1659-
1660-
diagnose_insn(decoder, "error", status, &insn);
1715+
#endif
1716+
}
16611717
}
16621718
}
16631719

@@ -1992,6 +2048,36 @@ static int drain_events_block(struct ptxed_decoder *decoder, uint64_t *time,
19922048
return status;
19932049
}
19942050

2051+
#if (LIBIPT_VERSION >= 0x202)
2052+
static int resync_block(struct ptxed_decoder *decoder,
2053+
const struct ptxed_options *options,
2054+
uint64_t *time)
2055+
{
2056+
int status;
2057+
2058+
if (!decoder || !options)
2059+
return -pte_internal;
2060+
2061+
for (;;) {
2062+
status = pt_blk_resync(decoder->variant.block);
2063+
if (status >= 0)
2064+
break;
2065+
2066+
if (status != -pte_event_ignored)
2067+
return status;
2068+
2069+
status = handle_one_event_block(decoder, options, time);
2070+
if (status < 0)
2071+
return status;
2072+
}
2073+
2074+
if ((status & pts_ip_suppressed) && !options->quiet)
2075+
printf("[disabled]\n");
2076+
2077+
return status;
2078+
}
2079+
#endif /* (LIBIPT_VERSION >= 0x202) */
2080+
19952081
static int decode_one_block(struct ptxed_decoder *decoder,
19962082
const struct ptxed_options *options,
19972083
struct ptxed_stats *stats,
@@ -2081,31 +2167,49 @@ static void decode_block(struct ptxed_decoder *decoder,
20812167
}
20822168

20832169
for (;;) {
2084-
status = drain_events_block(decoder, &time, status,
2085-
options);
2086-
if (status < 0)
2087-
break;
2170+
for (;;) {
2171+
status = drain_events_block(decoder, &time,
2172+
status, options);
2173+
if (status < 0)
2174+
break;
2175+
2176+
if (status & pts_eos) {
2177+
if (!(status & pts_ip_suppressed) &&
2178+
!options->quiet)
2179+
printf("[end of trace]\n");
2180+
2181+
status = -pte_eos;
2182+
break;
2183+
}
2184+
2185+
status = decode_one_block(decoder, options,
2186+
stats, &block, time);
2187+
if (status < 0)
2188+
break;
2189+
}
20882190

2089-
if (status & pts_eos) {
2090-
if (!(status & pts_ip_suppressed) &&
2091-
!options->quiet)
2092-
printf("[end of trace]\n");
2191+
/* We're done when we reach the end of the trace
2192+
* stream.
2193+
*/
2194+
if (status == -pte_eos)
2195+
return;
20932196

2094-
status = -pte_eos;
2095-
break;
2096-
}
2197+
diagnose_block(decoder, "error", status, &block);
20972198

2098-
status = decode_one_block(decoder, options, stats,
2099-
&block, time);
2100-
if (status < 0)
2199+
#if (LIBIPT_VERSION >= 0x202)
2200+
if (!options->resync_on_error)
21012201
break;
2102-
}
21032202

2104-
/* We're done when we reach the end of the trace stream. */
2105-
if (status == -pte_eos)
2203+
status = resync_block(decoder, options, &time);
2204+
if (status < 0) {
2205+
diagnose_block(decoder, "resync error", status,
2206+
&block);
2207+
break;
2208+
}
2209+
#else
21062210
break;
2107-
2108-
diagnose_block(decoder, "error", status, &block);
2211+
#endif
2212+
}
21092213
}
21102214
}
21112215

@@ -2824,6 +2928,12 @@ extern int main(int argc, char *argv[])
28242928
options.check = 1;
28252929
continue;
28262930
}
2931+
#if (LIBIPT_VERSION >= 0x202)
2932+
if (strcmp(arg, "--resync-on-error") == 0) {
2933+
options.resync_on_error = 1;
2934+
continue;
2935+
}
2936+
#endif
28272937
if (strcmp(arg, "--iscache-limit") == 0) {
28282938
uint64_t limit;
28292939

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
; Copyright (C) 2025 Intel Corporation
2+
; SPDX-License-Identifier: BSD-3-Clause
3+
;
4+
; Redistribution and use in source and binary forms, with or without
5+
; modification, are permitted provided that the following conditions are met:
6+
;
7+
; * Redistributions of source code must retain the above copyright notice,
8+
; this list of conditions and the following disclaimer.
9+
; * Redistributions in binary form must reproduce the above copyright notice,
10+
; this list of conditions and the following disclaimer in the documentation
11+
; and/or other materials provided with the distribution.
12+
; * Neither the name of Intel Corporation nor the names of its contributors
13+
; may be used to endorse or promote products derived from this software
14+
; without specific prior written permission.
15+
;
16+
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
; POSSIBILITY OF SUCH DAMAGE.
27+
28+
; Test resynchronizing after an error
29+
;
30+
; opt:ptxed --resync-on-error
31+
;
32+
33+
org 0x100000
34+
bits 64
35+
36+
; @pt p0: psb()
37+
; @pt p1: fup(3: %l0)
38+
; @pt p2: mode.exec(64bit)
39+
; @pt p3: psbend()
40+
41+
l0: jnz l3
42+
l1: hlt
43+
44+
; @pt p4: fup(1: %l2)
45+
; @pt p5: tip(1: %l4)
46+
l2: jmp rax
47+
l3: hlt
48+
l4: nop
49+
50+
; @pt p6: fup(1: %l5)
51+
; @pt p7: tip.pgd(0: %l5)
52+
l5: hlt
53+
54+
55+
; @pt .exp(ptdump)
56+
;%0p0 psb
57+
;%0p1 fup 3: %?l0
58+
;%0p2 mode.exec cs.l
59+
;%0p3 psbend
60+
;%0p4 fup 1: %?l2.2
61+
;%0p5 tip 1: %?l4.2
62+
;%0p6 fup 1: %?l5.2
63+
;%0p7 tip.pgd 0: %?l5.0
64+
65+
66+
; @pt .exp(ptxed)
67+
;%0l0
68+
;[%p5, %l0: error: trace stream does not match query]
69+
;[interrupt]
70+
;%0l4
71+
;[disabled]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; Copyright (C) 2025 Intel Corporation
2+
; SPDX-License-Identifier: BSD-3-Clause
3+
;
4+
; Redistribution and use in source and binary forms, with or without
5+
; modification, are permitted provided that the following conditions are met:
6+
;
7+
; * Redistributions of source code must retain the above copyright notice,
8+
; this list of conditions and the following disclaimer.
9+
; * Redistributions in binary form must reproduce the above copyright notice,
10+
; this list of conditions and the following disclaimer in the documentation
11+
; and/or other materials provided with the distribution.
12+
; * Neither the name of Intel Corporation nor the names of its contributors
13+
; may be used to endorse or promote products derived from this software
14+
; without specific prior written permission.
15+
;
16+
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
; POSSIBILITY OF SUCH DAMAGE.
27+
28+
; Test resynchronizing after an error
29+
;
30+
; opt:ptxed --resync-on-error
31+
;
32+
33+
org 0x100000
34+
bits 64
35+
36+
; @pt p0: psb()
37+
; @pt p1: fup(3: %l0)
38+
; @pt p2: mode.exec(64bit)
39+
; @pt p3: psbend()
40+
41+
l0: jnz l3
42+
l1: hlt
43+
44+
; @pt p4: tip(1: %l4)
45+
l2: jmp rax
46+
l3: hlt
47+
l4: nop
48+
49+
; @pt p5: ovf()
50+
51+
52+
; @pt .exp(ptdump)
53+
;%0p0 psb
54+
;%0p1 fup 3: %?l0
55+
;%0p2 mode.exec cs.l
56+
;%0p3 psbend
57+
;%0p4 tip 1: %?l4.2
58+
;%0p5 ovf
59+
60+
61+
; @pt .exp(ptxed)
62+
;%0l0
63+
;[%p4, %l0: error: trace stream does not match query]
64+
;[overflow]

0 commit comments

Comments
 (0)