hi all
I am announcing updates in the implementation of branch tracing using
coresight etm in GDB. in this update, functions and instruction history
are running successfully on single threaded applications. reverse
debugging is basically working with the limitation that sometimes cspr
register (register 25) is required but current implementation does not
provide it.
the feature requires linux kernel v 4.19 or higher with manual etm sink
setup. 5.9.1 or higher for automatic sink selection.
GDB gdb.btrace test suite was adapted to run on arm processors. here is
the summary of the gdb.btrace test results executed on an STM32MP157
(ARM cortex A7) with Linux kernel 5.9.1
=== gdb Summary ===
# of expected passes 390
# of unexpected failures 119
# of unsupported tests 4
following tests are 100% successful:
- buffer-size
- enable
- instruction_history
- function_call_history
- data
- delta
- cpu
- gcore
- record_goto-step
- dlopen
- vdso
- segv
GDB source code is available on
https://github.com/gzied/binutils-gdb/tree/gdb_arm_coresight
many thanks to GDB and linaro communities for their support
Kind Regards
Zied Guermazi
hi
Thanks Mike for your support, it was very helpful.
to put everything together, on arm, gdb inserts a sw breakpoint by
patching the code with an undefined instruction ( see comments in
arm-tdep.c line7687) when a breakpoint is hit, an exception number 9
"Undefined Instruction exception" is raised and a branch packet with
this info is generated in etm traces, the trap is get handled by the
kernel and it sends the appropriate signal to gdb process.
when the user continues the execution, gdb patches back the code and
executes the instruction. this leads to the instruction traced twice
with an exception in between, the same happens for next executed instruction
here is the log of decoded packets
[btrace] [ftrace] update insn: fun = main, file =
./function_call_history.c, level = 0, insn = [1; 2)
cs_etm_decoder_trace_element_callback: elem->elem_type
OCSD_GEN_TRC_ELEM_INSTR_RANGE */<= first execution attempt that raises
an undefined instruction exception/*
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400534
end addr = 0x400536
instructions count = 1
last_i_type: OCSD_INSTR_OTHER
last_i_subtype: OCSD_S_INSTR_NONE
last instruction was executed
last instruction size: 2
[btrace] [ftrace] update insn: fun = main, file =
./function_call_history.c, level = 0, insn = [1; 3)
cs_etm_decoder_trace_element_callback: elem->elem_type
OCSD_GEN_TRC_ELEM_EXCEPTION */<= the exception is traced/*
trace_chan_id: 18
exception number: 9 */<= undefined instruction exception/*
cs_etm_decoder_trace_element_callback: elem->elem_type
OCSD_GEN_TRC_ELEM_TRACE_ON
cs_etm_decoder_trace_element_callback: elem->elem_type
OCSD_GEN_TRC_ELEM_PE_CONTEXT
cs_etm_decoder_trace_element_callback: elem->elem_type
OCSD_GEN_TRC_ELEM_INSTR_RANGE */<= execution of the original instruction/*
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400534
end addr = 0x400536
instructions count = 1
last_i_type: OCSD_INSTR_OTHER
last_i_subtype: OCSD_S_INSTR_NONE
last instruction was executed
last instruction size: 2
as the code was changed during execution, it can not be reconstructed
during traces decoding.
in addition, and for tracing applications running on Linux, we are not
interested in capturing raised exceptions, we can consider rolling back
last instruction in ftraces. As this is not obvious, we can consider
ignoring the repeated instruction as a workaround.
for tracing bare metal software, we need to keep tracing exception, so
we can have a flag for ignoring exceptions, and activate or dis-activate
it according to the context.
what do you think about it, shall I go for implementing it as described
above?
Kind Regards
Zied Guermazi
On 02.11.20 12:59, Mike Leach wrote:
> Hi Zeid,
>
> On Sat, 31 Oct 2020 at 23:11, Zied Guermazi <zied.guermazi(a)trande.de> wrote:
>> hi,
>>
>> while testing the implementation in gdb of branch tracing on arm
>> processors using etm, I faced the the situation where a breakpoint was
>> set, was hit and then the execution of the program was continued. While
>> decoding generated traces, I got the address of the breakpoint
>> (0x400552) executed twice, and then the following address (0x400554)
>> also executed twice. the instruction at (0x400554) is a BL ( a function
>> call) and the second execution corrupts the function history.
>>
>> here is a dump of generated trace elements
>>
>>
>> ---------------------------------
>> trace_chan_id: 18
>> isa: CS_ETM_ISA_T32
>> start addr = 0x400552
>> end addr = 0x400554
>> instructions count = 1
>> last_i_type: OCSD_INSTR_OTHER
>> last_i_subtype: OCSD_S_INSTR_NONE
>> last instruction was executed
>> last instruction size: 2
>> ---------------------------------
>> trace_chan_id: 18
>> isa: CS_ETM_ISA_T32
>> start addr = 0x400552
>> end addr = 0x400554
>> instructions count = 1
>> last_i_type: OCSD_INSTR_OTHER
>> last_i_subtype: OCSD_S_INSTR_NONE
>> last instruction was executed
>> last instruction size: 2
>> ---------------------------------
>> trace_chan_id: 18
>> isa: CS_ETM_ISA_T32
>> start addr = 0x400554
>> end addr = 0x400558
>> instructions count = 1
>> last_i_type: OCSD_INSTR_BR
>> last_i_subtype: OCSD_S_INSTR_BR_LINK
>> last instruction was executed
>> last instruction size: 4
>> ---------------------------------
>> trace_chan_id: 18
>> isa: CS_ETM_ISA_T32
>> start addr = 0x400554
>> end addr = 0x400558
>> instructions count = 1
>> last_i_type: OCSD_INSTR_BR
>> last_i_subtype: OCSD_S_INSTR_BR_LINK
>> last instruction was executed
>> last instruction size: 4
>>
>> the explanation I have for this behavior is that :
>>
>> -when setting the software breakpoint, the memory content of the
>> instruction (at 0x400552) was altered to the instruction BKPT,
>>
>> -when the breakpoint was hit, the original opcode was set at (0x400552)
>> and a BKPT was set to the next instruction address (0x400554), then the
>> execution was continued
>>
>> -when the second breakpoint (0x400554) was hit, the a BKPT opcode was
>> set at (0x400552) and the original opcode was set at (0x400554) then the
>> execution was continued
>>
>> I am using the function "int target_read_code (CORE_ADDR memaddr,
>> gdb_byte *myaddr, ssize_t len)" to give program memory content to the
>> decoder. so the collected etm traces are correct, but, as memory was
>> altered in between, the decoder is "cheated".
>>
>> I need to identify the re-execution of code due to breakpoint handling,
>> and roll back its impact on etm decoding.
>>
>> is there a mean to get the actual content of program memory including
>> patched addresses?
>>
>> is there a means of getting the history of patched addresses during the
>> debugging of a program?
>>
>> what is the type and subtype of a BKPT instruction in a decoded trace
>> elements?
>>
> I can only really comment on this question. The type / subtype
> information in the output from the decoder is generated from the
> decoder walking the memory image of the executed trace - not from the
> trace packets themselves.
> The decoder classifies instructions according to how they will affect
> trace flow with the "other" category being set for the majority of
> instructions. The categories are: other, branch, indirect branch, ISB
> / DSB / DMB / WFI / WFE.
> These are important in program flow trace (PTM 1.x, ETM 4.x) as these
> determine which instruction we attach the E/N atoms to. BKPT will be
> classified as "other", if it is seen, as it has no effect on normal
> program flow. It will cause an exception which has a specific trace
> packet format.
>
> Regards
>
> Mike
>
>
>> do you have any other idea for handling this situation?
>>
>>
>> I am attaching the source code of the program as well as the
>> disassembled binary. the code was compiled as an application running on
>> linux on an ARMv7 A (STM32MP157 SoC). the breakpoint was set at line 43
>> in the source code (line 238 in the disassembled code)
>>
>>
>> Kind Regards
>>
>> Zied Guermazi
>>
>> _______________________________________________
>> CoreSight mailing list
>> CoreSight(a)lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/coresight
>
>
hi,
while testing the implementation in gdb of branch tracing on arm
processors using etm, I faced the the situation where a breakpoint was
set, was hit and then the execution of the program was continued. While
decoding generated traces, I got the address of the breakpoint
(0x400552) executed twice, and then the following address (0x400554)
also executed twice. the instruction at (0x400554) is a BL ( a function
call) and the second execution corrupts the function history.
here is a dump of generated trace elements
---------------------------------
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400552
end addr = 0x400554
instructions count = 1
last_i_type: OCSD_INSTR_OTHER
last_i_subtype: OCSD_S_INSTR_NONE
last instruction was executed
last instruction size: 2
---------------------------------
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400552
end addr = 0x400554
instructions count = 1
last_i_type: OCSD_INSTR_OTHER
last_i_subtype: OCSD_S_INSTR_NONE
last instruction was executed
last instruction size: 2
---------------------------------
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400554
end addr = 0x400558
instructions count = 1
last_i_type: OCSD_INSTR_BR
last_i_subtype: OCSD_S_INSTR_BR_LINK
last instruction was executed
last instruction size: 4
---------------------------------
trace_chan_id: 18
isa: CS_ETM_ISA_T32
start addr = 0x400554
end addr = 0x400558
instructions count = 1
last_i_type: OCSD_INSTR_BR
last_i_subtype: OCSD_S_INSTR_BR_LINK
last instruction was executed
last instruction size: 4
the explanation I have for this behavior is that :
-when setting the software breakpoint, the memory content of the
instruction (at 0x400552) was altered to the instruction BKPT,
-when the breakpoint was hit, the original opcode was set at (0x400552)
and a BKPT was set to the next instruction address (0x400554), then the
execution was continued
-when the second breakpoint (0x400554) was hit, the a BKPT opcode was
set at (0x400552) and the original opcode was set at (0x400554) then the
execution was continued
I am using the function "int target_read_code (CORE_ADDR memaddr,
gdb_byte *myaddr, ssize_t len)" to give program memory content to the
decoder. so the collected etm traces are correct, but, as memory was
altered in between, the decoder is "cheated".
I need to identify the re-execution of code due to breakpoint handling,
and roll back its impact on etm decoding.
is there a mean to get the actual content of program memory including
patched addresses?
is there a means of getting the history of patched addresses during the
debugging of a program?
what is the type and subtype of a BKPT instruction in a decoded trace
elements?
do you have any other idea for handling this situation?
I am attaching the source code of the program as well as the
disassembled binary. the code was compiled as an application running on
linux on an ARMv7 A (STM32MP157 SoC). the breakpoint was set at line 43
in the source code (line 238 in the disassembled code)
Kind Regards
Zied Guermazi
Progress:
* VIRT-65 [QEMU upstream maintainership]
+ more code review and assembly of the last pull request for
softfreeze for QEMU 5.2
+ noticed that our AArch32 Neon emulation doesn't work on big-endian
hosts. RTH fixed most of this and I wrote a couple of patches to
fix bugs in some insns that were only noticeable once we got out
of the "anything working on vectors is broken" state :-)
+ looked at trying to get our documentation to build with Sphinx 3,
which has made some annoying incompatible changes to the markup
it accepts
* VIRT-364 [QEMU support for ARMv8.1-M extensions]
+ started implementation of new insns VSCCLRM, CLRM, and
the new FP sysregs accessed via VLDR/VSTR
KVM Forum (virtual conference) was this week. Some interesting talks:
* Will Deacon on what Google is doing to introduce KVM into Android
* Marc Zyngier/Christoffer Dall on a virtual-only interrupt controller
that's less of a big lump of code to put on a security boundary than
a full-on GIC
* Salil Mehta on the current problems with doing Arm vCPU hotplug in KVM
thanks
-- PMM
VirtIO Initiative ([STR-9])
===========================
- Stratos sync call, discussion on AGL demo
- Google sync call
- Created a first cut of additional Xen work cards under [STR-16]
[STR-16] <https://projects.linaro.org/browse/STR-16>
VirtIO Portability Demo ([STR-13])
==================================
- Created a [branch with the experimental ioreq (virtio-mmio) support]
- developing understanding of the ioreq piece
- posted [PATCH] meson.build: fix building of Xen support for aarch64
Message-Id: <20201028174406.23424-1-alex.bennee(a)linaro.org>
- continued work and expanded into [branch to clean-up and add "virt"
machine]
[STR-13] <https://projects.linaro.org/browse/STR-13>
[branch with the experimental ioreq (virtio-mmio) support]
<http://git.linaro.org/people/alex.bennee/linux.git/shortlog/refs/heads/expe…>
[branch to clean-up and add "virt" machine]
<https://github.com/stsquad/qemu/tree/xen/add-xen-virt-machine>
Upstream Work ([QEMU-109])
==========================
- posted [PULL 0/8] testing and misc (gitdm, gitlab, docker, make)
Message-Id: <20201027095938.28673-1-alex.bennee(a)linaro.org>
[QEMU-109] <https://projects.linaro.org/browse/QEMU-109>
Other
=====
- KVM Forum 2020
Completed Reviews [2/2]
=======================
[PATCH 0/2] tcg: optimize across branches
Message-Id: <20201013222330.173525-1-richard.henderson(a)linaro.org>
[PATCH 00/15] remove bios_name variable
Message-Id: <20201026143028.3034018-8-pbonzini(a)redhat.com>
Absences
========
- Welsh lockdown next week
- Children at home
Current Review Queue
====================
* [PATCH 0/8] arm/virt: add usb support
Message-Id: <20201023071022.24916-1-kraxel(a)redhat.com>
Added: <2020-10-27 Tue>
* [PATCH 0/4] riscv: Add semihosting support [v10]
Message-Id: <20201026212853.92880-1-keithp(a)keithp.com>
Added: <2020-10-27 Tue>
* [PATCH v2 0/7] xen/arm: Unbreak ACPI
Message-Id: <20201023154156.6593-1-julien(a)xen.org>
Added: <2020-10-24 Sat>
* [PATCH v3 0/4] GitLab Custom Runners and Jobs (was: QEMU Gating CI)
Message-Id: <20201014052140.1146924-1-crosa(a)redhat.com>
Added: <2020-10-14 Wed>
--
Alex Bennée
* 2 days off
== Progress ==
* GCC upstream validation:
- reported several regressions/new failures
* GCC
- PR96767: patch accepted
- PR96770: patch accepted
- patch for C++ thunks with -mpure-code and cortex-m0: iterating, almost OK
- Neon intrinsics: vceqq, vceqz and vceqzq for p64 patch: no feedback
* benchmarking:
- Scripts to run coremark on stm32 now merged, debugging issues.
* infra:
- debugging issues with our docker containers
- added monitoring for disk space on dev machines
== Next ==
* GCC/cortex-M testing improvements & fixes
* cortex-m benchmarking
* MVE intrinsics improvements
[VIRT-327 # Richard's upstream QEMU work ]
More time than I expected on float128_muladd, adjusting the codebase to share
code with float64_muladd.
[VIRT-339 # ARMv8.5-BTI, Branch Target Identification ]
Posted v12, adjusting one of the smoke tests vs a distro linker bug (fixed in
mainline).
r~
VirtIO Initiative ([STR-9])
===========================
VirtIO RPMB ([STR-5])
=====================
- Synced with with Ulf/Illias on enhancements for eMMC stacks
- need to support 512 frames somehow for the CSD, everything else
should be fine
[STR-5] <https://projects.linaro.org/browse/STR-5>
VirtIO Portability Demo ([STR-13])
==================================
- More work on trying to get Xen working on MB
- more failures, this time GIC related. Might just stick to KVM
- Created a [branch with the experimental ioreq (virtio-mmio) support]
- Got Virgl based acceleration working on both TCG and KVM - so now
fast graphics!
- posted [PATCH v1 0/4] add guest-loader (for direct Xen boot)
Message-Id: <20201021170842.25762-1-alex.bennee(a)linaro.org>
[STR-13] <https://projects.linaro.org/browse/STR-13>
[branch with the experimental ioreq (virtio-mmio) support]
<http://git.linaro.org/people/alex.bennee/linux.git/shortlog/refs/heads/expe…>
Upstream Work ([QEMU-109])
==========================
- Some discussion on converting the final bits of 96/128 bit softfloat
- posted [RFC PATCH 0/8] fpu: experimental conversion of
float128_addsub Message-Id:
<20201020163738.27700-1-alex.bennee(a)linaro.org>
- partial reviewed [RFC PATCH 00/15] softfloat: alternate conversion
of float128_addsub Message-Id:
<20201021045149.1582203-1-richard.henderson(a)linaro.org>
- posted [PATCH v1 0/6] testing/next (gitdm, acceptance, docker,
gitlab) Message-Id: <20201021163136.27324-5-alex.bennee(a)linaro.org>
Other
=====
- reclaiming space for my gmail (98.5% used!)
Completed Reviews [1/1]
=======================
[PATCH 0/2] tcg: optimize across branches
Message-Id: <20201013222330.173525-1-richard.henderson(a)linaro.org>
Absences
========
- Welsh lockdown next week
- Children at home
Current Review Queue
====================
* [PATCH v3 0/4] GitLab Custom Runners and Jobs (was: QEMU Gating CI)
Message-Id: <20201014052140.1146924-1-crosa(a)redhat.com>
Added: <2020-10-14 Wed>
* [PATCH v6 0/5] Enable plugin support on msys2/mingw
Message-Id: <20201013002806.1447-1-luoyonggang(a)gmail.com>
Added: <2020-10-13 Tue>
* [PATCH v7 0/4] Improve cirrus msys2
Message-Id: <20201012233740.190-1-luoyonggang(a)gmail.com>
Added: <2020-10-13 Tue>
* [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch
Message-Id: <20200613213629.21984-1-salil.mehta(a)huawei.com>
Added: <2020-09-23 Wed>
--
Alex Bennée
* 2 days off
== Progress ==
* GCC upstream validation:
- identified several regressions, but they had already been reported
* GCC
- PR96767: no feedback
- PR96770: no feedback
- patch for C++ thunks with -mpure-code and cortex-m0: handling
further feedback
- Neon intrinsics: vceqq, vceqz and vceqzq for p64 patch: no feedback
* benchmarking:
- Scripts to run coremark on stm32 now merged, debugging issues. No
progress this week.
* infra:
- debugging issues with our docker containers
== Next ==
* GCC/cortex-M testing improvements & fixes
* cortex-m benchmarking
* MVE intrinsics improvements