From: Bernd Edlinger <bernd.edlinger@hotmail.de>
To: Andrew Burgess <andrew.burgess@embecosm.com>, gdb-patches@sourceware.org
Subject: [PATCHv4] Fix range end handling of inlined subroutines
Date: Fri, 13 Mar 2020 13:47:37 +0100 [thread overview]
Message-ID: <VE1PR03MB51817E38B1D1251974EB90EEE4FA0@VE1PR03MB5181.eurprd03.prod.outlook.com> (raw)
In-Reply-To: <AM6PR03MB5170F1560AA237DB22760697E4E10@AM6PR03MB5170.eurprd03.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 245 bytes --]
This is the updated version of my patch, with additional
information "why" this is done in the changelog,
and addressing all review comments so far.
I tested again, also together with my other patch,
all test results look good.
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-range-end-handling-of-inlined-subroutines.patch --]
[-- Type: text/x-patch; name="0001-Fix-range-end-handling-of-inlined-subroutines.patch", Size: 10992 bytes --]
From faec33a8d7fea3a990505eb9d65e6c93c0afd0eb Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 9 Feb 2020 21:13:17 +0100
Subject: [PATCH] Fix range end handling of inlined subroutines
Since the is_stmt is now handled, it becomes
possible to locate dubious is_stmt line entries
at the end of an inlined function, even if the
called inline function is in the same subfile.
When there is a sequence of line entries at the
same address where an inline range ends, and the
last item has is_stmt = 0, we force all previous
items to have is_stmt = 0 as well.
If the last line at that address has is_stmt = 1,
there is no need to change anything, since a step
over will always stop at that last line from the
same address, which is fine, since it is outside
the subroutine.
With this change we loose the ability to set
breakpoints on some lines using file:line syntax,
but the data is not completely lost, as the
line table is still holding those lines, just
with the is_stmt flag reset.
This is necessary as breakpoints on these lines
are problematic, because the call stack is often
wrong. From the block info they appear to be
located in the caller, but they are actually meant
to be part of the subroutine, therefore usually one
frame is missing from the callstack when the
execution stops there.
This is about the best we can do at the moment,
unless location view information are added to the
block ranges debug info structure, and location
views are implemented in gdb in general.
gdb:
2020-03-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
* buildsym.c (buildsym_compunit::record_inline_range_end,
patch_inline_end_pos): New helper functions.
(buildsym_compunit::end_symtab_with_blockvector): Patch line table.
(buildsym_compunit::~buildsym_compunit): Cleanup m_inline_end_vector.
* buildsym.h (buildsym_compunit::record_inline_range_end): Declare.
(buildsym_compunit::m_inline_end_vector,
buildsym_compunit::m_inline_end_vector_length,
buildsym_compunit::m_inline_end_vector_nitems): New data items.
* dwarf2/read.c (dwarf2_rnglists_process,
dwarf2_ranges_process): Don't ignore empty ranges here.
(dwarf2_ranges_read): Ignore empty ranges here.
(dwarf2_record_block_ranges): Pass end of range PC to
record_inline_range_end for inline functions.
gdb/testsuite:
2020-03-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
* gdb.cp/step-and-next-inline.exp: Adjust test.
---
gdb/buildsym.c | 86 +++++++++++++++++++++++++++
gdb/buildsym.h | 11 ++++
gdb/dwarf2/read.c | 22 ++++---
gdb/testsuite/gdb.cp/step-and-next-inline.exp | 17 ------
4 files changed, 110 insertions(+), 26 deletions(-)
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 960a36c..46f985a 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -113,6 +113,8 @@ struct pending_block
next1 = next->next;
xfree ((void *) next);
}
+
+ xfree (m_inline_end_vector);
}
struct macro_table *
@@ -729,6 +731,86 @@ struct blockvector *
}
\f
+/* Record a PC where a inlined subroutine ends. */
+
+void
+buildsym_compunit::record_inline_range_end (CORE_ADDR end)
+{
+ if (m_inline_end_vector == nullptr)
+ {
+ m_inline_end_vector_length = INITIAL_LINE_VECTOR_LENGTH;
+ m_inline_end_vector = (CORE_ADDR *)
+ xmalloc (sizeof (CORE_ADDR) * m_inline_end_vector_length);
+ m_inline_end_vector_nitems = 0;
+ }
+ else if (m_inline_end_vector_nitems == m_inline_end_vector_length)
+ {
+ m_inline_end_vector_length *= 2;
+ m_inline_end_vector = (CORE_ADDR *)
+ xrealloc ((char *) m_inline_end_vector,
+ sizeof (CORE_ADDR) * m_inline_end_vector_length);
+ }
+
+ m_inline_end_vector[m_inline_end_vector_nitems++] = end;
+}
+
+\f
+/* Patch the is_stmt bits at the given inline end address.
+ The line table has to be already sorted. */
+
+static void
+patch_inline_end_pos (struct linetable *table, CORE_ADDR end)
+{
+ int a = 2, b = table->nitems - 1;
+ struct linetable_entry *items = table->item;
+
+ /* We need at least two items with pc = end in the table.
+ The lowest usable items are at pos 0 and 1, the highest
+ usable items are at pos b - 2 and b - 1. */
+ if (a > b || end < items[1].pc || end > items[b - 2].pc)
+ return;
+
+ /* Look for the first item with pc > end in the range [a,b].
+ The previous element has pc = end or there is no match.
+ We set a = 2, since we need at least two consecutive elements
+ with pc = end to do anything useful.
+ We set b = nitems - 1, since we are not interested in the last
+ element which should be an end of sequence marker with line = 0
+ and is_stmt = 1. */
+ while (a < b)
+ {
+ int c = (a + b) / 2;
+
+ if (end < items[c].pc)
+ b = c;
+ else
+ a = c + 1;
+ }
+
+ a--;
+ if (items[a].pc != end || items[a].is_stmt)
+ return;
+
+ /* When there is a sequence of line entries at the same address
+ where an inline range ends, and the last item has is_stmt = 0,
+ we force all previous items to have is_stmt = 0 as well.
+ Setting breakpoints at those addresses is currently not
+ supported, since it is unclear if the previous addresses are
+ part of the subroutine or the calling program. */
+ do
+ {
+ /* We stop at the first line entry with a different address,
+ or when we see an end of sequence marker. */
+ a--;
+ if (items[a].pc != end || items[a].line == 0)
+ break;
+
+ items[a].is_stmt = 0;
+ }
+ while (a > 0);
+}
+
+\f
/* Subroutine of end_symtab to simplify it. Look for a subfile that
matches the main source file's basename. If there is only one, and
if the main source file doesn't have any symbol or line number
@@ -962,6 +1044,10 @@ struct compunit_symtab *
subfile->line_vector->item
+ subfile->line_vector->nitems,
lte_is_less_than);
+
+ for (int i = 0; i < m_inline_end_vector_nitems; i++)
+ patch_inline_end_pos (subfile->line_vector,
+ m_inline_end_vector[i]);
}
/* Allocate a symbol table if necessary. */
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index c768a4c..2845789 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -190,6 +190,8 @@ struct buildsym_compunit
void record_line (struct subfile *subfile, int line, CORE_ADDR pc,
bool is_stmt);
+ void record_inline_range_end (CORE_ADDR end);
+
struct compunit_symtab *get_compunit_symtab ()
{
return m_compunit_symtab;
@@ -397,6 +399,15 @@ struct buildsym_compunit
/* Pending symbols that are local to the lexical context. */
struct pending *m_local_symbols = nullptr;
+
+ /* Pending inline end range addresses. */
+ CORE_ADDR * m_inline_end_vector = nullptr;
+
+ /* Number of allocated inline end range addresses. */
+ int m_inline_end_vector_length = 0;
+
+ /* Number of pending inline end range addresses. */
+ int m_inline_end_vector_nitems = 0;
};
\f
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1706b96..6be008c 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -13609,10 +13609,6 @@ class process_die_scope
return false;
}
- /* Empty range entries have no effect. */
- if (range_beginning == range_end)
- continue;
-
range_beginning += base;
range_end += base;
@@ -13723,10 +13719,6 @@ class process_die_scope
return 0;
}
- /* Empty range entries have no effect. */
- if (range_beginning == range_end)
- continue;
-
range_beginning += base;
range_end += base;
@@ -13766,6 +13758,10 @@ class process_die_scope
retval = dwarf2_ranges_process (offset, cu,
[&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
{
+ /* Empty range entries have no effect. */
+ if (range_beginning == range_end)
+ return;
+
if (ranges_pst != NULL)
{
CORE_ADDR lowpc;
@@ -14003,6 +13999,7 @@ class process_die_scope
struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct attribute *attr;
struct attribute *attr_high;
+ bool inlined_subroutine = (die->tag == DW_TAG_inlined_subroutine);
attr_high = dwarf2_attr (die, DW_AT_high_pc, cu);
if (attr_high)
@@ -14018,7 +14015,10 @@ class process_die_scope
low = gdbarch_adjust_dwarf2_addr (gdbarch, low + baseaddr);
high = gdbarch_adjust_dwarf2_addr (gdbarch, high + baseaddr);
- cu->get_builder ()->record_block_range (block, low, high - 1);
+ if (inlined_subroutine)
+ cu->get_builder ()->record_inline_range_end (high);
+ if (low < high)
+ cu->get_builder ()->record_block_range (block, low, high - 1);
}
}
@@ -14043,6 +14043,10 @@ class process_die_scope
end += baseaddr;
start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
+ if (inlined_subroutine)
+ cu->get_builder ()->record_inline_range_end (end);
+ if (start == end)
+ return;
cu->get_builder ()->record_block_range (block, start, end - 1);
blockvec.emplace_back (start, end);
});
diff --git a/gdb/testsuite/gdb.cp/step-and-next-inline.exp b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
index acec48b..84c0901 100644
--- a/gdb/testsuite/gdb.cp/step-and-next-inline.exp
+++ b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
@@ -48,37 +48,20 @@ proc do_test { use_header } {
gdb_test "step" ".*" "step into get_alias_set"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 1"
- # It's possible that this first failure (when not using a header
- # file) is GCC's fault, though the remaining failures would best
- # be fixed by adding location views support (though it could be
- # that some easier heuristic could be figured out). Still, it is
- # not certain that the first failure wouldn't also be fixed by
- # having location view support, so for now it is tagged as such.
- if {!$use_header} { setup_kfail "*-*-*" symtab/25507 }
gdb_test "next" ".*TREE_TYPE.*" "next step 1"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 2"
gdb_test "next" ".*TREE_TYPE.*" "next step 2"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 3"
- if {!$use_header} { setup_kfail "*-*-*" symtab/25507 }
gdb_test "next" ".*TREE_TYPE.*" "next step 3"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 4"
- if {!$use_header} { setup_kfail "*-*-*" symtab/25507 }
gdb_test "next" "return 0.*" "next step 4"
gdb_test "bt" \
"\\s*\\#0\\s+(main|get_alias_set)\[^\r\]*${srcfile}:.*" \
"not in inline 5"
- if {!$use_header} {
- # With the debug from GCC 10.x (and earlier) GDB is currently
- # unable to successfully complete the following tests when we
- # are not using a header file.
- kfail symtab/25507 "stepping tests"
- return
- }
-
clean_restart ${executable}
if ![runto_main] {
--
1.9.1
next prev parent reply other threads:[~2020-03-13 12:47 UTC|newest]
Thread overview: 79+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-05 11:37 [PATCH 0/2] Line table is_stmt support Andrew Burgess
2020-02-05 11:37 ` [PATCH 2/2] gdb: Add support for tracking the DWARF line table is-stmt field Andrew Burgess
2020-02-05 17:55 ` Bernd Edlinger
2020-02-10 18:30 ` Bernd Edlinger
2020-02-11 13:57 ` Andrew Burgess
2020-02-14 20:05 ` Bernd Edlinger
2020-03-05 18:01 ` Bernd Edlinger
2020-03-08 12:50 ` [PATCHv2 0/2] Line table is_stmt support Andrew Burgess
2020-03-08 14:39 ` Bernd Edlinger
2020-03-10 23:01 ` Andrew Burgess
2020-03-11 6:50 ` Simon Marchi
2020-03-11 11:28 ` Andrew Burgess
2020-03-11 13:27 ` Simon Marchi
2020-04-03 22:21 ` [PATCH 0/2] More regression fixing from is-stmt patches Andrew Burgess
2020-04-03 22:21 ` [PATCH 1/2] gdb/testsuite: Move helper function into lib/dwarf.exp Andrew Burgess
2020-04-06 20:18 ` Tom Tromey
2020-04-14 11:18 ` Andrew Burgess
2020-04-03 22:21 ` [PATCH 2/2] gdb: Preserve is-stmt lines when switch between files Andrew Burgess
2020-04-04 18:07 ` Bernd Edlinger
2020-04-04 19:59 ` Bernd Edlinger
2020-04-04 22:23 ` Andrew Burgess
2020-04-05 0:04 ` Bernd Edlinger
2020-04-05 0:47 ` Bernd Edlinger
2020-04-05 8:55 ` Bernd Edlinger
2020-04-11 3:52 ` Bernd Edlinger
2020-04-12 17:13 ` Bernd Edlinger
2020-04-14 11:28 ` Andrew Burgess
2020-04-14 11:37 ` Bernd Edlinger
2020-04-14 11:41 ` Bernd Edlinger
2020-04-14 13:08 ` Andrew Burgess
2020-04-16 17:18 ` Andrew Burgess
2020-04-22 21:13 ` Tom Tromey
2020-04-25 7:06 ` Bernd Edlinger
2020-04-27 10:34 ` Andrew Burgess
2020-05-14 20:18 ` Tom Tromey
2020-05-14 22:39 ` Andrew Burgess
2020-05-15 3:35 ` Bernd Edlinger
2020-05-15 14:46 ` Andrew Burgess
2020-05-16 8:12 ` Bernd Edlinger
2020-05-17 17:26 ` Bernd Edlinger
2020-05-20 18:26 ` Andrew Burgess
2020-05-27 13:10 ` Andrew Burgess
2020-06-01 9:05 ` Andrew Burgess
2020-03-08 12:50 ` [PATCHv2 1/2] gdb/testsuite: Add is-stmt support to the DWARF compiler Andrew Burgess
2020-03-08 12:50 ` [PATCHv2 2/2] gdb: Add support for tracking the DWARF line table is-stmt field Andrew Burgess
2020-03-16 20:57 ` Tom Tromey
2020-03-16 22:37 ` Bernd Edlinger
2020-03-17 12:47 ` Tom Tromey
2020-03-17 18:23 ` Tom Tromey
2020-03-17 18:51 ` Bernd Edlinger
2020-03-17 18:56 ` Andrew Burgess
2020-03-17 20:18 ` Tom Tromey
2020-03-17 22:21 ` Andrew Burgess
2020-03-23 17:30 ` [PATCH 0/3] Keep duplicate line table entries Andrew Burgess
2020-03-23 17:30 ` [PATCH 1/3] gdb/testsuite: Add compiler options parameter to function_range helper Andrew Burgess
2020-04-01 18:31 ` Tom Tromey
2020-03-23 17:30 ` [PATCH 2/3] gdb/testsuite: Add support for DW_LNS_set_file to DWARF compiler Andrew Burgess
2020-04-01 18:32 ` Tom Tromey
2020-03-23 17:30 ` [PATCH 3/3] gdb: Don't remove duplicate entries from the line table Andrew Burgess
2020-04-01 18:34 ` Tom Tromey
2020-06-01 13:26 ` [PATCH 2/2] gdb: Add support for tracking the DWARF line table is-stmt field Pedro Alves
2020-02-06 9:01 ` Luis Machado
2020-02-11 15:39 ` Andrew Burgess
2020-02-09 21:07 ` [PATCH] Fix range end handling of inlined subroutines Bernd Edlinger
2020-02-10 21:48 ` Andrew Burgess
2020-02-22 6:39 ` [PATCHv2] " Bernd Edlinger
2020-03-08 14:57 ` [PATCHv3] " Bernd Edlinger
2020-03-11 22:02 ` Andrew Burgess
2020-03-12 18:21 ` Bernd Edlinger
2020-03-12 18:27 ` Christian Biesinger
2020-03-13 8:03 ` Bernd Edlinger
2020-03-17 22:27 ` Andrew Burgess
2020-03-19 1:33 ` Bernd Edlinger
2020-03-21 20:31 ` Bernd Edlinger
2020-03-23 17:53 ` Andrew Burgess
2020-03-23 20:58 ` Bernd Edlinger
2020-06-01 14:28 ` Pedro Alves
2020-03-13 12:47 ` Bernd Edlinger [this message]
2020-02-05 11:37 ` [PATCH 1/2] gdb/testsuite: Add is-stmt support to the DWARF compiler Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=VE1PR03MB51817E38B1D1251974EB90EEE4FA0@VE1PR03MB5181.eurprd03.prod.outlook.com \
--to=bernd.edlinger@hotmail.de \
--cc=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox