From d57e718f5727d9df930e46d2fc997a7eee466be2 Mon Sep 17 00:00:00 2001 From: Sayani Halder Date: Thu, 11 Jun 2026 20:18:51 +0100 Subject: [PATCH] opencsd: etm4: handle exception return addresses inside T32 instructions For M-profile tracing, the preferred exception return address may lie within a restartable 32-bit T32 instruction. The decoder searches for the preferred return address at instruction boundaries. When the address lies within a 32-bit Thumb instruction, it can be skipped, causing tracing to continue past the exception return point and emit an incorrect instruction range. Detect this case and stop tracing at the preferred return address when it falls within the current Thumb-2 instruction. Add regression snapshot tests covering exception return addresses at an instruction boundary, within a 32-bit T32 instruction, and at the next instruction boundary to validate the behaviour and prevent future regressions. Signed-off-by: Sayani Halder --- .../source/etmv4/trc_pkt_decode_etmv4i.cpp | 9 + decoder/tests/run_pkt_decode_tests.bash | 1 + decoder/tests/run_pkt_decode_tests.py | 1 + .../code_0x10000140.bin | Bin 0 -> 24 bytes .../nmi_partial_exec_snapshot/device1.ini | 29 +++ .../nmi_partial_exec_snapshot/device2.ini | 188 ++++++++++++++++++ .../nmi_partial_exec_snapshot.ppl | 43 ++++ .../nmi_partial_exec_snapshot/snapshot.ini | 11 + .../nmi_partial_exec_snapshot/trace.ini | 13 ++ .../nmi_partial_exec_snapshot/tracebuffer.bin | Bin 0 -> 44 bytes 10 files changed, 295 insertions(+) create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/code_0x10000140.bin create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/device1.ini create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/device2.ini create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/pkt_proc_logs/nmi_partial_exec_snapshot.ppl create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/snapshot.ini create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/trace.ini create mode 100644 decoder/tests/snapshots/nmi_partial_exec_snapshot/tracebuffer.bin diff --git a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp index 303a3235dd3c..a7bafa946562 100644 --- a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp @@ -2017,6 +2017,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WP while(WPRes == WP_NOT_FOUND) { + const ocsd_vaddr_t curr_instr_addr = m_instr_info.instr_addr; + // start off by reading next opcode; bytesReq = 4; err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode); @@ -2037,6 +2039,13 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WP { if (m_instr_info.instr_addr == nextAddrMatch) WPRes = WP_FOUND; + else if ((m_config->coreProfile() == profile_CortexM) && (m_instr_info.isa == ocsd_isa_thumb2) && (nextAddrMatch > curr_instr_addr) && (nextAddrMatch < m_instr_info.instr_addr)) + { + // For M-profile, a preferred exception return address can lie inside + // a restartable / interrupt-continuable 32-bit T32 instruction. + m_instr_info.instr_addr = nextAddrMatch; + WPRes = WP_FOUND; + } } else if (m_instr_info.type != OCSD_INSTR_OTHER) WPRes = WP_FOUND; diff --git a/decoder/tests/run_pkt_decode_tests.bash b/decoder/tests/run_pkt_decode_tests.bash index 8cf1d89873dc..89c4f9712442 100755 --- a/decoder/tests/run_pkt_decode_tests.bash +++ b/decoder/tests/run_pkt_decode_tests.bash @@ -57,6 +57,7 @@ declare -a test_dirs_decode=( "bugfix-exact-match" "itm_only_csformat" "itm_only_raw" + "nmi_partial_exec_snapshot" "juno_r1_1" "juno-ret-stck" "juno-uname-001" diff --git a/decoder/tests/run_pkt_decode_tests.py b/decoder/tests/run_pkt_decode_tests.py index f460470b1058..7b57b8595d7c 100644 --- a/decoder/tests/run_pkt_decode_tests.py +++ b/decoder/tests/run_pkt_decode_tests.py @@ -33,6 +33,7 @@ "juno-ret-stck", "juno-uname-001", "juno-uname-002", + "nmi_partial_exec_snapshot", "Snowball", "stm-issue-27", "stm_only", diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/code_0x10000140.bin b/decoder/tests/snapshots/nmi_partial_exec_snapshot/code_0x10000140.bin new file mode 100644 index 0000000000000000000000000000000000000000..b290ae238d471bd32af1bc39773d584a1499c90c GIT binary patch literal 24 UcmZR2AHvE0fB^**xHIer05UcMtN;K2 literal 0 HcmV?d00001 diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/device1.ini b/decoder/tests/snapshots/nmi_partial_exec_snapshot/device1.ini new file mode 100644 index 000000000000..e044469f5bf8 --- /dev/null +++ b/decoder/tests/snapshots/nmi_partial_exec_snapshot/device1.ini @@ -0,0 +1,29 @@ +[device] +name=Cortex-M33 +class=core +type=Cortex-M33 + +[regs] +CONTROL=0x00000000 +PC=0x10000140 +xPSR=0x01000000 +R12=0x00000000 +R11=0x00000000 +R10=0x00000000 +R9=0x00000000 +R8=0x00000000 +R7=0x00000000 +R6=0x00000000 +R5=0x00000000 +R4=0x00000000 +R3=0x00000000 +R2=0x00000000 +R1=0x00000000 +R0=0x00000000 +LR=0x00000000 +SP=0x00000000 + +[dump1] +address=0x10000140 +length=0x18 +file=code_0x10000140.bin diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/device2.ini b/decoder/tests/snapshots/nmi_partial_exec_snapshot/device2.ini new file mode 100644 index 000000000000..b4d2e1708bf1 --- /dev/null +++ b/decoder/tests/snapshots/nmi_partial_exec_snapshot/device2.ini @@ -0,0 +1,188 @@ +[device] +name=CSETM_4 +class=trace_source +type=ETM4.4 + +[regs] +TRCPROCSELR(0x2)=0x00000000 +TRCCONFIGR(0x4)=0x00000880 +TRCAUXCTLR(0x6)=0x00000000 +TRCEVENTCTL0R(0x8)=0x00000000 +TRCEVENTCTL1R(0x9)=0x00000000 +TRCSTALLCTLR(0xB)=0x00000000 +TRCTSCTLR(0xC)=0x00000000 +TRCSYNCPR(0xD)=0x0000000B +TRCCCCTLR(0xE)=0x00000004 +TRCBBCTLR(0xF)=0x00000000 +TRCTRACEIDR(0x10)=0x00000006 +TRCQCTLR(0x11)=0x00000000 +TRCVICTLR(0x20)=0x00000201 +TRCVIIECTLR(0x21)=0x00000000 +TRCVISSCTLR(0x22)=0x00000000 +TRCVIPCSSCTLR(0x23)=0x00000000 +TRCVDCTLR(0x28)=0x00000001 +TRCVDSACCTLR(0x29)=0x00000000 +TRCVDARCCTLR(0x2A)=0x00000000 +TRCSEQEVR0(0x40)=0x00000000 +TRCSEQEVR1(0x41)=0x00000000 +TRCSEQEVR2(0x42)=0x00000000 +TRCSEQRSTEVR(0x46)=0x00000000 +TRCSEQSTR(0x47)=0x00000000 +TRCEXTINSELR(0x48)=0x00000000 +TRCCNTRLDVR0(0x50)=0x00000000 +TRCCNTRLDVR1(0x51)=0x00000000 +TRCCNTRLDVR2(0x52)=0x00000000 +TRCCNTRLDVR3(0x53)=0x00000000 +TRCCNTCTLR0(0x54)=0x00000000 +TRCCNTCTLR1(0x55)=0x00000000 +TRCCNTCTLR2(0x56)=0x00000000 +TRCCNTCTLR3(0x57)=0x00000000 +TRCCNTVR0(0x58)=0x00000000 +TRCCNTVR1(0x59)=0x00000000 +TRCCNTVR2(0x5A)=0x00000000 +TRCCNTVR3(0x5B)=0x00000000 +TRCIDR8(0x60)=0x00000010 +TRCIDR9(0x61)=0x00000020 +TRCIDR10(0x62)=0x00000002 +TRCIDR11(0x63)=0x00000000 +TRCIDR12(0x64)=0x00000001 +TRCIDR13(0x65)=0x00000000 +TRCIMSPEC0(0x70)=0x00000000 +TRCIMSPEC1(0x71)=0x00000000 +TRCIMSPEC2(0x72)=0x00000000 +TRCIMSPEC3(0x73)=0x00000000 +TRCIMSPEC4(0x74)=0x00000000 +TRCIMSPEC5(0x75)=0x00000000 +TRCIMSPEC6(0x76)=0x00000000 +TRCIMSPEC7(0x77)=0x00000000 +TRCIDR0(0x78)=0x20000CA1 +TRCIDR1(0x79)=0x4100F443 +TRCIDR2(0x7A)=0x00001088 +TRCIDR3(0x7B)=0x05090004 +TRCIDR4(0x7C)=0x00174124 +TRCIDR5(0x7D)=0x28C70004 +TRCIDR6(0x7E)=0x00000000 +TRCIDR7(0x7F)=0x00000000 +TRCRSCTLR2(0x82)=0x00040000 +TRCRSCTLR3(0x83)=0x00020001 +TRCRSCTLR4(0x84)=0x00000000 +TRCRSCTLR5(0x85)=0x00000000 +TRCRSCTLR6(0x86)=0x00000000 +TRCRSCTLR7(0x87)=0x00000000 +TRCRSCTLR8(0x88)=0x00000000 +TRCRSCTLR9(0x89)=0x00000000 +TRCRSCTLR10(0x8A)=0x00000000 +TRCRSCTLR11(0x8B)=0x00000000 +TRCRSCTLR12(0x8C)=0x00000000 +TRCRSCTLR13(0x8D)=0x00000000 +TRCRSCTLR14(0x8E)=0x00000000 +TRCRSCTLR15(0x8F)=0x00000000 +TRCRSCTLR16(0x90)=0x00000000 +TRCRSCTLR17(0x91)=0x00000000 +TRCRSCTLR18(0x92)=0x00000000 +TRCRSCTLR19(0x93)=0x00000000 +TRCRSCTLR20(0x94)=0x00000000 +TRCRSCTLR21(0x95)=0x00000000 +TRCRSCTLR22(0x96)=0x00000000 +TRCRSCTLR23(0x97)=0x00000000 +TRCRSCTLR24(0x98)=0x00000000 +TRCRSCTLR25(0x99)=0x00000000 +TRCRSCTLR26(0x9A)=0x00000000 +TRCRSCTLR27(0x9B)=0x00000000 +TRCRSCTLR28(0x9C)=0x00000000 +TRCRSCTLR29(0x9D)=0x00000000 +TRCRSCTLR30(0x9E)=0x00000000 +TRCRSCTLR31(0x9F)=0x00000000 +TRCSSCCR0(0xA0)=0x00000000 +TRCSSCCR1(0xA1)=0x00000000 +TRCSSCCR2(0xA2)=0x00000000 +TRCSSCCR3(0xA3)=0x00000000 +TRCSSCCR4(0xA4)=0x00000000 +TRCSSCCR5(0xA5)=0x00000000 +TRCSSCCR6(0xA6)=0x00000000 +TRCSSCCR7(0xA7)=0x00000000 +TRCSSCSR0(0xA8)=0x0000000F +TRCSSCSR1(0xA9)=0x00000000 +TRCSSCSR2(0xAA)=0x00000000 +TRCSSCSR3(0xAB)=0x00000000 +TRCSSCSR4(0xAC)=0x00000000 +TRCSSCSR5(0xAD)=0x00000000 +TRCSSCSR6(0xAE)=0x00000000 +TRCSSCSR7(0xAF)=0x00000000 +TRCSSPCICR0(0xB0)=0x00000000 +TRCSSPCICR1(0xB1)=0x00000000 +TRCSSPCICR2(0xB2)=0x00000000 +TRCSSPCICR3(0xB3)=0x00000000 +TRCSSPCICR4(0xB4)=0x00000000 +TRCSSPCICR5(0xB5)=0x00000000 +TRCSSPCICR6(0xB6)=0x00000000 +TRCSSPCICR7(0xB7)=0x00000000 +TRCACVR0(0x100)=0x0000000000000000 +TRCACVR1(0x102)=0x0000000000000000 +TRCACVR2(0x104)=0x0000000000000000 +TRCACVR3(0x106)=0x0000000000000000 +TRCACVR4(0x108)=0x0000000000000000 +TRCACVR5(0x10A)=0x0000000000000000 +TRCACVR6(0x10C)=0x0000000000000000 +TRCACVR7(0x10E)=0x0000000000000000 +TRCACVR8(0x110)=0x0000000000000000 +TRCACVR9(0x112)=0x0000000000000000 +TRCACVR10(0x114)=0x0000000000000000 +TRCACVR11(0x116)=0x0000000000000000 +TRCACVR12(0x118)=0x0000000000000000 +TRCACVR13(0x11A)=0x0000000000000000 +TRCACVR14(0x11C)=0x0000000000000000 +TRCACVR15(0x11E)=0x0000000000000000 +TRCACATR0(0x120)=0x0000000000000000 +TRCACATR1(0x122)=0x0000000000000000 +TRCACATR2(0x124)=0x0000000000000000 +TRCACATR3(0x126)=0x0000000000000000 +TRCACATR4(0x128)=0x0000000000000000 +TRCACATR5(0x12A)=0x0000000000000000 +TRCACATR6(0x12C)=0x0000000000000000 +TRCACATR7(0x12E)=0x0000000000000000 +TRCACATR8(0x130)=0x0000000000000000 +TRCACATR9(0x132)=0x0000000000000000 +TRCACATR10(0x134)=0x0000000000000000 +TRCACATR11(0x136)=0x0000000000000000 +TRCACATR12(0x138)=0x0000000000000000 +TRCACATR13(0x13A)=0x0000000000000000 +TRCACATR14(0x13C)=0x0000000000000000 +TRCACATR15(0x13E)=0x0000000000000000 +TRCDVCVR0(0x140)=0x0000000000000000 +TRCDVCVR1(0x142)=0x0000000000000000 +TRCDVCVR2(0x144)=0x0000000000000000 +TRCDVCVR3(0x146)=0x0000000000000000 +TRCDVCVR4(0x148)=0x0000000000000000 +TRCDVCVR5(0x14A)=0x0000000000000000 +TRCDVCVR6(0x14C)=0x0000000000000000 +TRCDVCVR7(0x14E)=0x0000000000000000 +TRCDVCMR0(0x160)=0x0000000000000000 +TRCDVCMR1(0x162)=0x0000000000000000 +TRCDVCMR2(0x164)=0x0000000000000000 +TRCDVCMR3(0x166)=0x0000000000000000 +TRCDVCMR4(0x168)=0x0000000000000000 +TRCDVCMR5(0x16A)=0x0000000000000000 +TRCDVCMR6(0x16C)=0x0000000000000000 +TRCDVCMR7(0x16E)=0x0000000000000000 +TRCCIDCVR0(0x180)=0x0000000000000000 +TRCCIDCVR1(0x182)=0x0000000000000000 +TRCCIDCVR2(0x184)=0x0000000000000000 +TRCCIDCVR3(0x186)=0x0000000000000000 +TRCCIDCVR4(0x188)=0x0000000000000000 +TRCCIDCVR5(0x18A)=0x0000000000000000 +TRCCIDCVR6(0x18C)=0x0000000000000000 +TRCCIDCVR7(0x18E)=0x0000000000000000 +TRCVMIDCVR0(0x190)=0x0000000000000000 +TRCVMIDCVR1(0x192)=0x0000000000000000 +TRCVMIDCVR2(0x194)=0x0000000000000000 +TRCVMIDCVR3(0x196)=0x0000000000000000 +TRCVMIDCVR4(0x198)=0x0000000000000000 +TRCVMIDCVR5(0x19A)=0x0000000000000000 +TRCVMIDCVR6(0x19C)=0x0000000000000000 +TRCVMIDCVR7(0x19E)=0x0000000000000000 +TRCCIDCCTLR0(0x1A0)=0x00000000 +TRCCIDCCTLR1(0x1A1)=0x00000000 +TRCVMIDCCTLR0(0x1A2)=0x00000000 +TRCVMIDCCTLR1(0x1A3)=0x00000000 +TRCAUTHSTATUS(0x3EE)=0x000000C0 diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/pkt_proc_logs/nmi_partial_exec_snapshot.ppl b/decoder/tests/snapshots/nmi_partial_exec_snapshot/pkt_proc_logs/nmi_partial_exec_snapshot.ppl new file mode 100644 index 000000000000..2eb59e98d6ac --- /dev/null +++ b/decoder/tests/snapshots/nmi_partial_exec_snapshot/pkt_proc_logs/nmi_partial_exec_snapshot.ppl @@ -0,0 +1,43 @@ +Trace Packet Lister: CS Decode library testing +----------------------------------------------- + +** Library Version : 1.8.2 + +Test Command Line:- +bin/linux64/rel/trc_pkt_lister -ss_dir snapshots/nmi_partial_exec_snapshot -decode -no_time_print -logfilename results/nmi_partial_exec_snapshot.ppl + +Trace Packet Lister : reading snapshot from path snapshots/nmi_partial_exec_snapshot +Using CSTMC_TRACE_FIFO as trace source +Trace Packet Lister : Protocol printer ETMV4I on Trace ID 0x0 +Trace Packet Lister : Set trace element decode printer +Gen_Info : Mapped Memory Accessors +Gen_Info : FileAcc; Range::0x10000140:10000157; Mem Space::Any +Filename=snapshots/nmi_partial_exec_snapshot/code_0x10000140.bin +Gen_Info : ======================== +Idx:0; ID:0; [0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 ]; I_ASYNC : Alignment Synchronisation. +Idx:0; ID:6; OCSD_GEN_TRC_ELEM_NO_SYNC( [init-decoder]) +Idx:12; ID:0; [0x01 0x00 ]; I_TRACE_INFO : Trace Info.; INFO=0x0 { CC.0 }; Decoder Sync point TINFO +Idx:14; ID:0; [0x04 ]; I_TRACE_ON : Trace On. +Idx:15; ID:0; [0x83 0x20 0x01 0x00 0x10 0x00 ]; I_ADDR_CTXT_L_32IS1 : Address & Context, Long, 32 bit, IS1.; Addr=0x0000000010000140; Ctxt: AArch32, EL0, S; +Idx:21; ID:0; [0x06 0x05 ]; I_EXCEPT : Exception.; NMI; Ret Addr Follows; +Idx:23; ID:0; [0x96 0x21 ]; I_ADDR_S_IS1 : Address, Short, IS1.; Addr=0x0000000010000142 ~[0x42] +Idx:25; ID:0; [0x83 0x2a 0x01 0x00 0x10 0x03 ]; I_ADDR_CTXT_L_32IS1 : Address & Context, Long, 32 bit, IS1.; Addr=0x0000000010000154; Ctxt: AArch32, EL3, S; +Idx:31; ID:0; [0xf7 ]; I_ATOM_F1 : Atom format 1.; E +Idx:32; ID:0; [0x07 ]; I_EXCEPT_RTN : Exception Return. +Idx:33; ID:0; [0x83 0x20 0x01 0x00 0x10 0x00 ]; I_ADDR_CTXT_L_32IS1 : Address & Context, Long, 32 bit, IS1.; Addr=0x0000000010000140; Ctxt: AArch32, EL0, S; +Idx:39; ID:0; [0xf7 ]; I_ATOM_F1 : Atom format 1.; E +Idx:40; ID:0; [0x2d 0x04 ]; I_COMMIT : Commit; Commit(4) +Idx:14; ID:6; OCSD_GEN_TRC_ELEM_TRACE_ON( [begin or filter]) +Idx:15; ID:6; OCSD_GEN_TRC_ELEM_PE_CONTEXT((ISA=T32) EL0S; 32-bit; ) +Idx:21; ID:6; OCSD_GEN_TRC_ELEM_INSTR_RANGE(exec range=0x10000140:[0x10000142] num_i(1) last_sz(4) (ISA=T32) E --- ) +Idx:21; ID:6; OCSD_GEN_TRC_ELEM_EXCEPTION(pref ret addr:0x10000142; excep num (0x02) ) +Idx:25; ID:6; OCSD_GEN_TRC_ELEM_PE_CONTEXT((ISA=T32) EL3S; 32-bit; ) +Idx:31; ID:6; OCSD_GEN_TRC_ELEM_INSTR_RANGE(exec range=0x10000154:[0x10000156] num_i(1) last_sz(2) (ISA=T32) E iBR V7:impl ret) +Idx:32; ID:6; OCSD_GEN_TRC_ELEM_EXCEPTION_RET() +Idx:33; ID:6; OCSD_GEN_TRC_ELEM_PE_CONTEXT((ISA=T32) EL0S; 32-bit; ) +Idx:39; ID:6; OCSD_GEN_TRC_ELEM_INSTR_RANGE(exec range=0x10000140:[0x10000146] num_i(2) last_sz(2) (ISA=T32) E BR ) +Idx:42; ID:0; [0x00 0x03 ]; I_DISCARD : Discard. +Idx:42; ID:6; OCSD_GEN_TRC_ELEM_NO_SYNC( [discard]) +Idx:42; ID:6; OCSD_GEN_TRC_ELEM_EO_TRACE( [end-of-trace]) +ID:0 END OF TRACE DATA +Trace Packet Lister : Trace buffer done, processed 44 bytes. diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/snapshot.ini b/decoder/tests/snapshots/nmi_partial_exec_snapshot/snapshot.ini new file mode 100644 index 000000000000..0ac0181a5a04 --- /dev/null +++ b/decoder/tests/snapshots/nmi_partial_exec_snapshot/snapshot.ini @@ -0,0 +1,11 @@ +; OpenCSD v8-M NMI partial execution snapshot - split memory maps + +[snapshot] +version=1.0 + +[device_list] +device1=device1.ini +device2=device2.ini + +[trace] +metadata=trace.ini diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/trace.ini b/decoder/tests/snapshots/nmi_partial_exec_snapshot/trace.ini new file mode 100644 index 000000000000..30a05c21ead3 --- /dev/null +++ b/decoder/tests/snapshots/nmi_partial_exec_snapshot/trace.ini @@ -0,0 +1,13 @@ +[trace_buffers] +buffers=buffer0 + +[buffer0] +name=CSTMC_TRACE_FIFO +file=tracebuffer.bin +format=source_data + +[core_trace_sources] +Cortex-M33=CSETM_4 + +[source_buffers] +CSETM_4=CSTMC_TRACE_FIFO diff --git a/decoder/tests/snapshots/nmi_partial_exec_snapshot/tracebuffer.bin b/decoder/tests/snapshots/nmi_partial_exec_snapshot/tracebuffer.bin new file mode 100644 index 0000000000000000000000000000000000000000..82b6c05ef1ac978c7bb1ed7b236e9805630d4fbf GIT binary patch literal 44 mcmZQzfP)4`29{<8Mg{=}Hr8p1&00Vf^LKWL$ah^924(