GDB: etm traces decoding and breakpoints for arm targets

Zied Guermazi <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
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
function_call_history.s (text/plain, 8.6 KB)
function_call_history:     file format elf32-littlearm


Disassembly of section .init:

00000380 <_init>:
 380:	e92d4008 	push	{r3, lr}
 384:	eb000023 	bl	418 <call_weak_fn>
 388:	e8bd8008 	pop	{r3, pc}

Disassembly of section .plt:

0000038c <.plt>:
 38c:	e52de004 	push	{lr}		; (str lr, [sp, #-4]!)
 390:	e59fe004 	ldr	lr, [pc, #4]	; 39c <.plt+0x10>
 394:	e08fe00e 	add	lr, pc, lr
 398:	e5bef008 	ldr	pc, [lr, #8]!
 39c:	00010c2c 	.word	0x00010c2c

000003a0 <__cxa_finalize@plt>:
 3a0:	e28fc600 	add	ip, pc, #0, 12
 3a4:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
 3a8:	e5bcfc2c 	ldr	pc, [ip, #3116]!	; 0xc2c

000003ac <__libc_start_main@plt>:
 3ac:	e28fc600 	add	ip, pc, #0, 12
 3b0:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
 3b4:	e5bcfc24 	ldr	pc, [ip, #3108]!	; 0xc24

000003b8 <__gmon_start__@plt>:
 3b8:	e28fc600 	add	ip, pc, #0, 12
 3bc:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
 3c0:	e5bcfc1c 	ldr	pc, [ip, #3100]!	; 0xc1c

000003c4 <abort@plt>:
 3c4:	e28fc600 	add	ip, pc, #0, 12
 3c8:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
 3cc:	e5bcfc14 	ldr	pc, [ip, #3092]!	; 0xc14

Disassembly of section .text:

000003d0 <_start>:
 3d0:	f04f 0b00 	mov.w	fp, #0
 3d4:	f04f 0e00 	mov.w	lr, #0
 3d8:	bc02      	pop	{r1}
 3da:	466a      	mov	r2, sp
 3dc:	b404      	push	{r2}
 3de:	b401      	push	{r0}
 3e0:	f8df a024 	ldr.w	sl, [pc, #36]	; 408 <_start+0x38>
 3e4:	a308      	add	r3, pc, #32	; (adr r3, 408 <_start+0x38>)
 3e6:	449a      	add	sl, r3
 3e8:	f8df c020 	ldr.w	ip, [pc, #32]	; 40c <_start+0x3c>
 3ec:	f85a c00c 	ldr.w	ip, [sl, ip]
 3f0:	f84d cd04 	str.w	ip, [sp, #-4]!
 3f4:	4b06      	ldr	r3, [pc, #24]	; (410 <_start+0x40>)
 3f6:	f85a 3003 	ldr.w	r3, [sl, r3]
 3fa:	4806      	ldr	r0, [pc, #24]	; (414 <_start+0x44>)
 3fc:	f85a 0000 	ldr.w	r0, [sl, r0]
 400:	f7ff efd4 	blx	3ac <__libc_start_main@plt>
 404:	f7ff efde 	blx	3c4 <abort@plt>
 408:	00010bc0 	.word	0x00010bc0
 40c:	0000001c 	.word	0x0000001c
 410:	0000002c 	.word	0x0000002c
 414:	00000030 	.word	0x00000030

00000418 <call_weak_fn>:
 418:	e59f3014 	ldr	r3, [pc, #20]	; 434 <call_weak_fn+0x1c>
 41c:	e59f2014 	ldr	r2, [pc, #20]	; 438 <call_weak_fn+0x20>
 420:	e08f3003 	add	r3, pc, r3
 424:	e7932002 	ldr	r2, [r3, r2]
 428:	e3520000 	cmp	r2, #0
 42c:	012fff1e 	bxeq	lr
 430:	eaffffe0 	b	3b8 <__gmon_start__@plt>
 434:	00010ba0 	.word	0x00010ba0
 438:	00000028 	.word	0x00000028

0000043c <deregister_tm_clones>:
 43c:	4806      	ldr	r0, [pc, #24]	; (458 <deregister_tm_clones+0x1c>)
 43e:	4b07      	ldr	r3, [pc, #28]	; (45c <deregister_tm_clones+0x20>)
 440:	4478      	add	r0, pc
 442:	4a07      	ldr	r2, [pc, #28]	; (460 <deregister_tm_clones+0x24>)
 444:	447b      	add	r3, pc
 446:	4283      	cmp	r3, r0
 448:	447a      	add	r2, pc
 44a:	d003      	beq.n	454 <deregister_tm_clones+0x18>
 44c:	4b05      	ldr	r3, [pc, #20]	; (464 <deregister_tm_clones+0x28>)
 44e:	58d3      	ldr	r3, [r2, r3]
 450:	b103      	cbz	r3, 454 <deregister_tm_clones+0x18>
 452:	4718      	bx	r3
 454:	4770      	bx	lr
 456:	bf00      	nop
 458:	00010bc4 	.word	0x00010bc4
 45c:	00010bc0 	.word	0x00010bc0
 460:	00010b7c 	.word	0x00010b7c
 464:	00000024 	.word	0x00000024

00000468 <register_tm_clones>:
 468:	4808      	ldr	r0, [pc, #32]	; (48c <register_tm_clones+0x24>)
 46a:	4b09      	ldr	r3, [pc, #36]	; (490 <register_tm_clones+0x28>)
 46c:	4478      	add	r0, pc
 46e:	4a09      	ldr	r2, [pc, #36]	; (494 <register_tm_clones+0x2c>)
 470:	447b      	add	r3, pc
 472:	1a19      	subs	r1, r3, r0
 474:	447a      	add	r2, pc
 476:	1089      	asrs	r1, r1, #2
 478:	eb01 71d1 	add.w	r1, r1, r1, lsr #31
 47c:	1049      	asrs	r1, r1, #1
 47e:	d003      	beq.n	488 <register_tm_clones+0x20>
 480:	4b05      	ldr	r3, [pc, #20]	; (498 <register_tm_clones+0x30>)
 482:	58d3      	ldr	r3, [r2, r3]
 484:	b103      	cbz	r3, 488 <register_tm_clones+0x20>
 486:	4718      	bx	r3
 488:	4770      	bx	lr
 48a:	bf00      	nop
 48c:	00010b98 	.word	0x00010b98
 490:	00010b94 	.word	0x00010b94
 494:	00010b50 	.word	0x00010b50
 498:	00000034 	.word	0x00000034

0000049c <__do_global_dtors_aux>:
 49c:	b508      	push	{r3, lr}
 49e:	4b0a      	ldr	r3, [pc, #40]	; (4c8 <__do_global_dtors_aux+0x2c>)
 4a0:	4a0a      	ldr	r2, [pc, #40]	; (4cc <__do_global_dtors_aux+0x30>)
 4a2:	447b      	add	r3, pc
 4a4:	447a      	add	r2, pc
 4a6:	781b      	ldrb	r3, [r3, #0]
 4a8:	b96b      	cbnz	r3, 4c6 <__do_global_dtors_aux+0x2a>
 4aa:	4b09      	ldr	r3, [pc, #36]	; (4d0 <__do_global_dtors_aux+0x34>)
 4ac:	58d3      	ldr	r3, [r2, r3]
 4ae:	b123      	cbz	r3, 4ba <__do_global_dtors_aux+0x1e>
 4b0:	4b08      	ldr	r3, [pc, #32]	; (4d4 <__do_global_dtors_aux+0x38>)
 4b2:	447b      	add	r3, pc
 4b4:	6818      	ldr	r0, [r3, #0]
 4b6:	f7ff ef74 	blx	3a0 <__cxa_finalize@plt>
 4ba:	f7ff ffbf 	bl	43c <deregister_tm_clones>
 4be:	4b06      	ldr	r3, [pc, #24]	; (4d8 <__do_global_dtors_aux+0x3c>)
 4c0:	2201      	movs	r2, #1
 4c2:	447b      	add	r3, pc
 4c4:	701a      	strb	r2, [r3, #0]
 4c6:	bd08      	pop	{r3, pc}
 4c8:	00010b62 	.word	0x00010b62
 4cc:	00010b20 	.word	0x00010b20
 4d0:	00000020 	.word	0x00000020
 4d4:	00010b4e 	.word	0x00010b4e
 4d8:	00010b42 	.word	0x00010b42

000004dc <frame_dummy>:
 4dc:	e7c4      	b.n	468 <register_tm_clones>
 4de:	bf00      	nop

000004e0 <inc>:
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

int
inc (int i)
{
 4e0:	b480      	push	{r7}
 4e2:	b083      	sub	sp, #12
 4e4:	af00      	add	r7, sp, #0
 4e6:	6078      	str	r0, [r7, #4]
  return i+1;
 4e8:	687b      	ldr	r3, [r7, #4]
 4ea:	3301      	adds	r3, #1
}
 4ec:	4618      	mov	r0, r3
 4ee:	370c      	adds	r7, #12
 4f0:	46bd      	mov	sp, r7
 4f2:	f85d 7b04 	ldr.w	r7, [sp], #4
 4f6:	4770      	bx	lr

000004f8 <fib>:

int
fib (int n)
{
 4f8:	b590      	push	{r4, r7, lr}
 4fa:	b083      	sub	sp, #12
 4fc:	af00      	add	r7, sp, #0
 4fe:	6078      	str	r0, [r7, #4]
  if (n <= 1)
 500:	687b      	ldr	r3, [r7, #4]
 502:	2b01      	cmp	r3, #1
 504:	dc01      	bgt.n	50a <fib+0x12>
    return n;
 506:	687b      	ldr	r3, [r7, #4]
 508:	e00c      	b.n	524 <fib+0x2c>

  return fib(n-2) + fib(n-1);
 50a:	687b      	ldr	r3, [r7, #4]
 50c:	3b02      	subs	r3, #2
 50e:	4618      	mov	r0, r3
 510:	f7ff fff2 	bl	4f8 <fib>
 514:	4604      	mov	r4, r0
 516:	687b      	ldr	r3, [r7, #4]
 518:	3b01      	subs	r3, #1
 51a:	4618      	mov	r0, r3
 51c:	f7ff ffec 	bl	4f8 <fib>
 520:	4603      	mov	r3, r0
 522:	4423      	add	r3, r4
}
 524:	4618      	mov	r0, r3
 526:	370c      	adds	r7, #12
 528:	46bd      	mov	sp, r7
 52a:	bd90      	pop	{r4, r7, pc}

0000052c <main>:

int
main (void)
{
 52c:	b580      	push	{r7, lr}
 52e:	b082      	sub	sp, #8
 530:	af00      	add	r7, sp, #0
  int i, j;

  for (i = 0; i < 10; i++)
 532:	2300      	movs	r3, #0
 534:	603b      	str	r3, [r7, #0]
 536:	e009      	b.n	54c <main+0x20>
    j += inc(i);
 538:	6838      	ldr	r0, [r7, #0]
 53a:	f7ff ffd1 	bl	4e0 <inc>
 53e:	4602      	mov	r2, r0
 540:	687b      	ldr	r3, [r7, #4]
 542:	4413      	add	r3, r2
 544:	607b      	str	r3, [r7, #4]
  for (i = 0; i < 10; i++)
 546:	683b      	ldr	r3, [r7, #0]
 548:	3301      	adds	r3, #1
 54a:	603b      	str	r3, [r7, #0]
 54c:	683b      	ldr	r3, [r7, #0]
 54e:	2b09      	cmp	r3, #9
 550:	ddf2      	ble.n	538 <main+0xc>

  j += fib(3); /* bp.1 */
 552:	2003      	movs	r0, #3
 554:	f7ff ffd0 	bl	4f8 <fib>
 558:	4602      	mov	r2, r0
 55a:	687b      	ldr	r3, [r7, #4]
 55c:	4413      	add	r3, r2
 55e:	607b      	str	r3, [r7, #4]
  return j; /* bp.2 */
 560:	687b      	ldr	r3, [r7, #4]
}
 562:	4618      	mov	r0, r3
 564:	3708      	adds	r7, #8
 566:	46bd      	mov	sp, r7
 568:	bd80      	pop	{r7, pc}
	...

0000056c <__libc_csu_init>:
 56c:	e92d 43f8 	stmdb	sp!, {r3, r4, r5, r6, r7, r8, r9, lr}
 570:	4607      	mov	r7, r0
 572:	4e0c      	ldr	r6, [pc, #48]	; (5a4 <__libc_csu_init+0x38>)
 574:	4688      	mov	r8, r1
 576:	4d0c      	ldr	r5, [pc, #48]	; (5a8 <__libc_csu_init+0x3c>)
 578:	4691      	mov	r9, r2
 57a:	447e      	add	r6, pc
 57c:	f7ff ef00 	blx	380 <_init>
 580:	447d      	add	r5, pc
 582:	1b76      	subs	r6, r6, r5
 584:	10b6      	asrs	r6, r6, #2
 586:	d00a      	beq.n	59e <__libc_csu_init+0x32>
 588:	3d04      	subs	r5, #4
 58a:	2400      	movs	r4, #0
 58c:	3401      	adds	r4, #1
 58e:	f855 3f04 	ldr.w	r3, [r5, #4]!
 592:	464a      	mov	r2, r9
 594:	4641      	mov	r1, r8
 596:	4638      	mov	r0, r7
 598:	4798      	blx	r3
 59a:	42a6      	cmp	r6, r4
 59c:	d1f6      	bne.n	58c <__libc_csu_init+0x20>
 59e:	e8bd 83f8 	ldmia.w	sp!, {r3, r4, r5, r6, r7, r8, r9, pc}
 5a2:	bf00      	nop
 5a4:	0001094e 	.word	0x0001094e
 5a8:	00010944 	.word	0x00010944

000005ac <__libc_csu_fini>:
 5ac:	4770      	bx	lr
 5ae:	bf00      	nop

Disassembly of section .fini:

000005b0 <_fini>:
 5b0:	e92d4008 	push	{r3, lr}
 5b4:	e8bd8008 	pop	{r3, pc}
function_call_history.c (text/x-csrc, 1 KB)
/* This testcase is part of GDB, the GNU debugger.

   Copyright 2013-2019 Free Software Foundation, Inc.

   Contributed by Intel Corp. <[email protected]>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

int
inc (int i)
{
  return i+1;
}

int
fib (int n)
{
  if (n <= 1)
    return n;

  return fib(n-2) + fib(n-1);
}

int
main (void)
{
  int i, j;

  for (i = 0; i < 10; i++)
    j += inc(i);

  j += fib(3); /* bp.1 */
  return j; /* bp.2 */
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.