[PATCH 5/6] disasm: determine preceding lines independent of last_line

Markus Metzger
2015-09-21T14:55:08Z

In do_mixed_source_and_assembly, we check for source lines without code
between the last line that was printed and the next line to be printed.
We print those extra source lines before the line for the next instruction.

Since instructions can now be in any order, it is no longer guaranteed that
last_line corresponds to the previous instruction.

Change the boundary from last_line to the first line in the same function and
remove the first-line-to-be-printed check.

This will now print source lines without code also before the first
instruction.

2015-09-21 Markus Metzger <markus.t.metzger@intel.com>

* disasm.c: Include block.h
(first_line_in_pc_function): New.
(do_mixed_source_and_assembly): Search for lines without code until the
first line in the same function.
---
gdb/disasm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/gdb/disasm.c b/gdb/disasm.c
index 32e4bc1..2503657 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -25,6 +25,7 @@
#include "gdbcore.h"
#include "dis-asm.h"
#include "source.h"
+#include "block.h"

/* Disassemble functions.
FIXME: We should get rid of all the duplicate code in gdb that does
@@ -63,6 +64,54 @@ line_has_code_p (struct symtab *symtab, int line)
return 0;
}

+/* Return the first line in the function that contains PC or zero if the line
+ can't be determined. */
+
+static int
+first_line_in_pc_function (struct symtab *symtab, CORE_ADDR pc)
+{
+ const struct symbol *sym;
+ const struct block *block;
+ struct linetable *ltable;
+ CORE_ADDR high, low;
+ int nlines, ix, first;
+
+ sym = find_pc_function (pc);
+ if (sym == NULL)
+ return 0;
+
+ block = SYMBOL_BLOCK_VALUE (sym);
+ if (block == NULL)
+ return 0;
+
+ ltable = SYMTAB_LINETABLE (symtab);
+ if (ltable == NULL)
+ return 0;
+
+ low = BLOCK_START (block);
+ high = BLOCK_END (block);
+ nlines = ltable->nitems;
+ first = INT_MAX;
+
+ /* Skip preceding functions. */
+ for (ix = 0; ix < nlines && ltable->item[ix].pc < low ; ++ix);
+
+ /* Determine the first line in the function PC range. */
+ for (; ix < nlines && ltable->item[ix].pc < high; ++ix)
+ {
+ int line = ltable->item[ix].line;
+
+ if (line != 0 && line < first)
+ first = line;
+ }
+
+ /* Return zero if we didn't find any line entry. */
+ if (first == INT_MAX)
+ first = 0;
+
+ return first;
+}
+
/* Like target_read_memory, but slightly different parameters. */
static int
dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
@@ -510,13 +559,16 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
/* Same source file as last time. */
if (sal.symtab != NULL)
{
- if (sal.line > last_line + 1 && last_line != 0)
+ int first_line;
+
+ /* Print preceding source lines not associated with code.
+ Restrict the search to the current function. */
+ first_line = first_line_in_pc_function (sal.symtab, insn->addr);
+ if (first_line > 0)
{
int l;

- /* Several preceding source lines. Print the trailing ones
- not associated with code that we'll print later. */
- for (l = sal.line - 1; l > last_line; --l)
+ for (l = sal.line - 1; l >= first_line; --l)
{
if (line_has_code_p (sal.symtab, l))
break;
--
1.8.3.1