[3/3] Handle the effect of skipping prologue

Message ID 1426785208-18301-4-git-send-email-qiyaoltc@gmail.com
State New
Headers show

Commit Message

Yao Qi March 19, 2015, 5:13 p.m.
From: Yao Qi <yao.qi@linaro.org>

break-asm-file.exp has some manually written dwarf to create some line
number entries like this,

  [0x0000013d]  Extended opcode 2: set Address to 0x40053f
  [0x00000144]  Advance Line by 4 to 7
  [0x00000146]  Copy
  [0x00000147]  Extended opcode 2: set Address to 0x400541
  [0x0000014e]  Advance Line by 1 to 8
  [0x00000150]  Copy
  [0x00000151]  Extended opcode 2: set Address to 0x400547
  [0x00000158]  Extended opcode 1: End of Sequence

0x40053f is the start address of function func, and is mapped to line
7.  0x400541 is within function func, and is mapped to line 8.

(gdb) disassemble /r 0x40053f,+8
Dump of assembler code from 0x40053f to 0x400547:
   0x000000000040053f <func+0>: 00 00   add    %al,(%rax)
   0x0000000000400541 <func+2>: 00 00   add    %al,(%rax)
   0x0000000000400543 <func+4>: 00 00   add    %al,(%rax)
   0x0000000000400545 <func+6>: 00 00   add    %al,(%rax)

in the following test,

(gdb) break a/break-asm-file0.s:func
Breakpoint 1 at 0x40053f: file a/break-asm-file0.s, line 7.

As we can see, breakpoint is set at the start address of function func
on x86, which means no prologue is skipped.  On other targets, such as
arm and aarch64, breakpoint is set at the address *after* the start
address, which is mapped to line 8.  Then test fails.

In fact, it is lucky this test doesn't fail on x86 and x86_64, whose
gdbarch method skip_prologue doesn't reply on skip_prologue_using_sal
if producer isn't clang.

  if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
    {
      CORE_ADDR post_prologue_pc
	= skip_prologue_using_sal (gdbarch, func_addr);
      struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);

      /* Clang always emits a line note before the prologue and another
	 one after.  We trust clang to emit usable line notes.  */
      if (post_prologue_pc
	  && (cust != NULL
	      && COMPUNIT_PRODUCER (cust) != NULL
	      && startswith (COMPUNIT_PRODUCER (cust), "clang ")))
        return max (start_pc, post_prologue_pc);
    }

so it doesn't return and go further to prologue analyser.  Since ".int 0"
isn't an instruction of prologue, nothing is skipped, starting address
is used, and test passes.

however, on targets which don't have such producer checking, the first
line number entry is skipped, and skip_prologue_using_sal returns sal
represents the second line number entry.

The idea of this patch is to force GDB stop at somewhere which is stilled
mapped to line 7 after skipping prologue.  I choose to add a new line
number entry for the following instruction but mapped to the same line (7),
because I see the comments in dwarf2read.c,

   ... fact that two consecutive
   line number entries for the same line is a heuristic used by gcc
   to denote the end of the prologue.

then the line table becomes:

  [0x000000d4]  Extended opcode 2: set Address to 0x400529
  [0x000000db]  Advance Line by 4 to 7
  [0x000000dd]  Copy
  [0x000000de]  Extended opcode 2: set Address to 0x40052a
  [0x000000e5]  Advance Line by 0 to 7
  [0x000000e7]  Copy
  [0x000000e8]  Extended opcode 2: set Address to 0x40052b
  [0x000000ef]  Advance Line by 1 to 8
  [0x000000f1]  Copy
  [0x000000f2]  Extended opcode 2: set Address to 0x40052c
  [0x000000f9]  Extended opcode 1: End of Sequence

gdb/testsuite:

2015-03-19  Yao Qi  <yao.qi@linaro.org>

	PR testsuite/18139
	* gdb.linespec/break-asm-file0.s (func): New label .Lfunc_2.
	Add a line number entry for the same line.
	* gdb.linespec/break-asm-file1.s (func): New label .Lfunc_2.
	Add a line number entry for the same line.
---
 gdb/testsuite/gdb.linespec/break-asm-file0.s | 14 ++++++++++++++
 gdb/testsuite/gdb.linespec/break-asm-file1.s | 14 ++++++++++++++
 2 files changed, 28 insertions(+)

Patch hide | download patch | download mbox

diff --git a/gdb/testsuite/gdb.linespec/break-asm-file0.s b/gdb/testsuite/gdb.linespec/break-asm-file0.s
index 42c4213..dbc4398 100644
--- a/gdb/testsuite/gdb.linespec/break-asm-file0.s
+++ b/gdb/testsuite/gdb.linespec/break-asm-file0.s
@@ -38,6 +38,8 @@  func:
 	nop
 .Lfunc_1:
 	nop
+.Lfunc_2:
+	nop
 .Lend_func:
 	.size func, .-func
 .Lend_text1:
@@ -202,6 +204,18 @@  func:
 	.byte		2
 	.4byte		.Lfunc_1
 
+	/* A line number entry for the same line (7) denotes the end */
+	/* of prologue.  */
+	.byte		3	/* DW_LNS_advance_line */
+	.sleb128	0	/* ... to 7 */
+
+	.byte		1	/* DW_LNS_copy */
+
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lfunc_2
+	
 	.byte		3	/* DW_LNS_advance_line */
 	.sleb128	1	/* ... to 8 */
 
diff --git a/gdb/testsuite/gdb.linespec/break-asm-file1.s b/gdb/testsuite/gdb.linespec/break-asm-file1.s
index a1e7a42..4372626 100644
--- a/gdb/testsuite/gdb.linespec/break-asm-file1.s
+++ b/gdb/testsuite/gdb.linespec/break-asm-file1.s
@@ -34,6 +34,8 @@  func:
 	nop
 .Lfunc_1:
 	nop
+.Lfunc_2:
+	nop
 .Lend_func:
 	.size func, .-func
 .Lend_text1:
@@ -228,6 +230,18 @@  func:
 	.byte		2
 	.4byte		.Lfunc_1
 
+	/* A line number entry for the same line (7) denotes the end */
+	/* of prologue.  */
+	.byte		3	/* DW_LNS_advance_line */
+	.sleb128	0	/* ... to 7 */
+
+	.byte		1	/* DW_LNS_copy */
+
+	.byte		0	/* DW_LNE_set_address */
+	.uleb128	5
+	.byte		2
+	.4byte		.Lfunc_2
+
 	.byte		3	/* DW_LNS_advance_line */
 	.sleb128	1	/* ... to 8 */