Merge remote-tracking branch 'up/f33' into f33-riscv64

Signed-off-by: David Abdurachmanov <david.abdurachmanov@gmail.com>
This commit is contained in:
David Abdurachmanov 2021-05-21 08:47:40 +03:00
commit f669e0cd55
Signed by: davidlt
GPG Key ID: 8B7F1DA0E2C9FDBB
8 changed files with 804 additions and 6 deletions

3
.gitignore vendored
View File

@ -1,6 +1,5 @@
/binutils-gdb
/gdb-libstdc++-v3-python-8.1.1-20180626.tar.xz
/gdb-9.2.tar.xz
/v2.0.2.tar.gz
/gdb-10.1.tar.gz
/gdb-10.1.tar.xz
/v2.0.4.tar.gz

View File

@ -37,6 +37,10 @@ Patch009: gdb-6.3-test-movedir-20050125.patch
#=fedoratest
Patch010: gdb-6.3-threaded-watchpoints2-20050225.patch
# Notify observers that the inferior has been created
#=fedoratest
Patch011: gdb-6.3-inferior-notification-20050721.patch
# Verify printing of inherited members test
#=fedoratest
Patch012: gdb-6.3-inheritancetest-20050726.patch
@ -98,6 +102,10 @@ Patch025: gdb-6.6-testsuite-timeouts.patch
#=fedoratest
Patch026: gdb-6.6-bz237572-ppc-atomic-sequence-test.patch
# Test kernel VDSO decoding while attaching to an i386 process.
#=fedoratest
Patch027: gdb-6.3-attach-see-vdso-test.patch
# Test leftover zombie process (BZ 243845).
#=fedoratest
Patch028: gdb-6.5-bz243845-stale-testing-zombie-test.patch
@ -131,6 +139,14 @@ Patch034: gdb-6.7-testsuite-stable-results.patch
#=fedoratest
Patch035: gdb-6.5-ia64-libunwind-leak-test.patch
# Test hiding unexpected breakpoints on intentional step commands.
#=fedoratest
Patch036: gdb-6.5-missed-trap-on-step-test.patch
# Test gcore memory and time requirements for large inferiors.
#=fedoratest
Patch037: gdb-6.5-gcore-buffer-limit-test.patch
# Test GCORE for shmid 0 shared memory mappings.
#=fedoratest: But it is broken anyway, sometimes the case being tested is not reproducible.
Patch038: gdb-6.3-mapping-zero-inode-test.patch
@ -378,3 +394,9 @@ Patch096: gdb-vla-intel-fix-print-char-array.patch
# =fedoratest
Patch097: gdb-rhbz1553104-s390x-arch12-test.patch
# Backport fix for frame_id_p assertion failure (RH BZ 1909902).
Patch098: gdb-rhbz1909902-frame_id_p-assert-1.patch
# Backport patch #2 which fixes a frame_id_p assertion failure (RH BZ 1909902).
Patch099: gdb-rhbz1909902-frame_id_p-assert-2.patch

View File

@ -8,6 +8,7 @@
%patch008 -p1
%patch009 -p1
%patch010 -p1
%patch011 -p1
%patch012 -p1
%patch013 -p1
%patch014 -p1
@ -23,6 +24,7 @@
%patch024 -p1
%patch025 -p1
%patch026 -p1
%patch027 -p1
%patch028 -p1
%patch029 -p1
%patch030 -p1
@ -31,6 +33,8 @@
%patch033 -p1
%patch034 -p1
%patch035 -p1
%patch036 -p1
%patch037 -p1
%patch038 -p1
%patch039 -p1
%patch040 -p1
@ -91,3 +95,5 @@
%patch095 -p1
%patch096 -p1
%patch097 -p1
%patch098 -p1
%patch099 -p1

View File

@ -95,3 +95,5 @@ gdb-rhbz1398387-tab-crash-test.patch
gdb-archer.patch
gdb-vla-intel-fix-print-char-array.patch
gdb-rhbz1553104-s390x-arch12-test.patch
gdb-rhbz1909902-frame_id_p-assert-1.patch
gdb-rhbz1909902-frame_id_p-assert-2.patch

View File

@ -0,0 +1,593 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Fri, 30 Oct 2020 18:26:15 +0100
Subject: gdb-rhbz1909902-frame_id_p-assert-1.patch
;; Backport fix for frame_id_p assertion failure (RH BZ 1909902).
Make scoped_restore_current_thread's cdtors exception free (RFC)
If the remote target closes while we're reading registers/memory for
restoring the selected frame in scoped_restore_current_thread's dtor,
the corresponding TARGET_CLOSE_ERROR error is swallowed by the
scoped_restore_current_thread's dtor, because letting exceptions
escape from a dtor is bad. It isn't great to lose that errors like
that, though. I've been thinking about how to avoid it, and I came up
with this patch.
The idea here is to make scoped_restore_current_thread's dtor do as
little as possible, to avoid any work that might throw in the first
place. And to do that, instead of having the dtor call
restore_selected_frame, which re-finds the previously selected frame,
just record the frame_id/level of the desired selected frame, and have
get_selected_frame find the frame the next time it is called. In
effect, this implements most of Cagney's suggestion, here:
/* On demand, create the selected frame and then return it. If the
selected frame can not be created, this function prints then throws
an error. When MESSAGE is non-NULL, use it for the error message,
otherwize use a generic error message. */
/* FIXME: cagney/2002-11-28: At present, when there is no selected
frame, this function always returns the current (inner most) frame.
It should instead, when a thread has previously had its frame
selected (but not resumed) and the frame cache invalidated, find
and then return that thread's previously selected frame. */
extern struct frame_info *get_selected_frame (const char *message);
The only thing missing to fully implement that would be to make
reinit_frame_cache just clear selected_frame instead of calling
select_frame(NULL), and the call select_frame(NULL) explicitly in the
places where we really wanted reinit_frame_cache to go back to the
current frame too. That can done separately, though, I'm not
proposing to do that in this patch.
Note that this patch renames restore_selected_frame to
lookup_selected_frame, and adds a new restore_selected_frame function
that doesn't throw, to be paired with the also-new save_selected_frame
function.
There's a restore_selected_frame function in infrun.c that I think can
be replaced by the new one in frame.c.
Also done in this patch is make the get_selected_frame's parameter be
optional, so that we don't have to pass down nullptr explicitly all
over the place.
lookup_selected_frame should really move from thread.c to frame.c, but
I didn't do that here, just to avoid churn in the patch while it
collects comments. I did make it extern and declared it in frame.h
already, preparing for the move. I will do the move as a follow up
patch if people agree with this approach.
Incidentally, this patch alone would fix the crashes fixed by the
previous patches in the series, because with this,
scoped_restore_current_thread's constructor doesn't throw either.
gdb/ChangeLog:
* blockframe.c (block_innermost_frame): Use get_selected_frame.
* frame.c
(scoped_restore_selected_frame::scoped_restore_selected_frame):
Use save_selected_frame. Save language as well.
(scoped_restore_selected_frame::~scoped_restore_selected_frame):
Use restore_selected_frame, and restore language as well.
(selected_frame_id, selected_frame_level): New.
(selected_frame): Update comments.
(save_selected_frame, restore_selected_frame): New.
(get_selected_frame): Use lookup_selected_frame.
(get_selected_frame_if_set): Delete.
(select_frame): Record selected_frame_level and selected_frame_id.
* frame.h (scoped_restore_selected_frame) <m_level, m_lang>: New
fields.
(get_selected_frame): Make 'message' parameter optional.
(get_selected_frame_if_set): Delete declaration.
(select_frame): Update comments.
(save_selected_frame, restore_selected_frame)
(lookup_selected_frame): Declare.
* gdbthread.h (scoped_restore_current_thread) <m_lang>: New field.
* infrun.c (struct infcall_control_state) <selected_frame_level>:
New field.
(save_infcall_control_state): Use save_selected_frame.
(restore_selected_frame): Delete.
(restore_infcall_control_state): Use restore_selected_frame.
* stack.c (select_frame_command_core, frame_command_core): Use
get_selected_frame.
* thread.c (restore_selected_frame): Rename to ...
(lookup_selected_frame): ... this and make extern. Select the
current frame if the frame level is -1.
(scoped_restore_current_thread::restore): Also restore the
language.
(scoped_restore_current_thread::~scoped_restore_current_thread):
Don't try/catch.
(scoped_restore_current_thread::scoped_restore_current_thread):
Save the language as well. Use save_selected_frame.
Change-Id: I73fd1cfc40d8513c28e5596383b7ecd8bcfe700f
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -464,14 +464,10 @@ find_gnu_ifunc_target_type (CORE_ADDR resolver_funaddr)
struct frame_info *
block_innermost_frame (const struct block *block)
{
- struct frame_info *frame;
-
if (block == NULL)
return NULL;
- frame = get_selected_frame_if_set ();
- if (frame == NULL)
- frame = get_current_frame ();
+ frame_info *frame = get_selected_frame ();
while (frame != NULL)
{
const struct block *frame_block = get_frame_block (frame, NULL);
diff --git a/gdb/frame.c b/gdb/frame.c
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -317,17 +317,15 @@ frame_stash_invalidate (void)
/* See frame.h */
scoped_restore_selected_frame::scoped_restore_selected_frame ()
{
- m_fid = get_frame_id (get_selected_frame (NULL));
+ m_lang = current_language->la_language;
+ save_selected_frame (&m_fid, &m_level);
}
/* See frame.h */
scoped_restore_selected_frame::~scoped_restore_selected_frame ()
{
- frame_info *frame = frame_find_by_id (m_fid);
- if (frame == NULL)
- warning (_("Unable to restore previously selected frame."));
- else
- select_frame (frame);
+ restore_selected_frame (m_fid, m_level);
+ set_language (m_lang);
}
/* Flag to control debugging. */
@@ -1685,10 +1683,63 @@ get_current_frame (void)
}
/* The "selected" stack frame is used by default for local and arg
- access. May be zero, for no selected frame. */
-
+ access.
+
+ The "single source of truth" for the selected frame is the
+ SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL pair.
+
+ Frame IDs can be saved/restored across reinitializing the frame
+ cache, while frame_info pointers can't (frame_info objects are
+ invalidated). If we know the corresponding frame_info object, it
+ is cached in SELECTED_FRAME.
+
+ If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
+ and the target has stack and is stopped, the selected frame is the
+ current (innermost) frame. This means that SELECTED_FRAME_LEVEL is
+ never 0 and SELECTED_FRAME_ID is never the ID of the innermost
+ frame.
+
+ If SELECTED_FRAME_ID / SELECTED_FRAME_LEVEL are null_frame_id / -1,
+ and the target has no stack or is executing, then there's no
+ selected frame. */
+static frame_id selected_frame_id = null_frame_id;
+static int selected_frame_level = -1;
+
+/* The cached frame_info object pointing to the selected frame.
+ Looked up on demand by get_selected_frame. */
static struct frame_info *selected_frame;
+/* See frame.h. */
+
+void
+save_selected_frame (frame_id *frame_id, int *frame_level)
+ noexcept
+{
+ *frame_id = selected_frame_id;
+ *frame_level = selected_frame_level;
+}
+
+/* See frame.h. */
+
+void
+restore_selected_frame (frame_id frame_id, int frame_level)
+ noexcept
+{
+ /* save_selected_frame never returns level == 0, so we shouldn't see
+ it here either. */
+ gdb_assert (frame_level != 0);
+
+ /* FRAME_ID can be null_frame_id only IFF frame_level is -1. */
+ gdb_assert ((frame_level == -1 && !frame_id_p (frame_id))
+ || (frame_level != -1 && frame_id_p (frame_id)));
+
+ selected_frame_id = frame_id;
+ selected_frame_level = frame_level;
+
+ /* Will be looked up later by get_selected_frame. */
+ selected_frame = nullptr;
+}
+
bool
has_stack_frames ()
{
@@ -1715,9 +1766,7 @@ has_stack_frames ()
return true;
}
-/* Return the selected frame. Always non-NULL (unless there isn't an
- inferior sufficient for creating a frame) in which case an error is
- thrown. */
+/* See frame.h. */
struct frame_info *
get_selected_frame (const char *message)
@@ -1726,24 +1775,14 @@ get_selected_frame (const char *message)
{
if (message != NULL && !has_stack_frames ())
error (("%s"), message);
- /* Hey! Don't trust this. It should really be re-finding the
- last selected frame of the currently selected thread. This,
- though, is better than nothing. */
- select_frame (get_current_frame ());
+
+ lookup_selected_frame (selected_frame_id, selected_frame_level);
}
/* There is always a frame. */
gdb_assert (selected_frame != NULL);
return selected_frame;
}
-/* If there is a selected frame, return it. Otherwise, return NULL. */
-
-struct frame_info *
-get_selected_frame_if_set (void)
-{
- return selected_frame;
-}
-
/* This is a variant of get_selected_frame() which can be called when
the inferior does not have a frame; in that case it will return
NULL instead of calling error(). */
@@ -1756,12 +1795,42 @@ deprecated_safe_get_selected_frame (void)
return get_selected_frame (NULL);
}
-/* Select frame FI (or NULL - to invalidate the current frame). */
+/* Select frame FI (or NULL - to invalidate the selected frame). */
void
select_frame (struct frame_info *fi)
{
selected_frame = fi;
+ selected_frame_level = frame_relative_level (fi);
+ if (selected_frame_level == 0)
+ {
+ /* Treat the current frame especially -- we want to always
+ save/restore it without warning, even if the frame ID changes
+ (see lookup_selected_frame). E.g.:
+
+ // The current frame is selected, the target had just stopped.
+ {
+ scoped_restore_selected_frame restore_frame;
+ some_operation_that_changes_the_stack ();
+ }
+ // scoped_restore_selected_frame's dtor runs, but the
+ // original frame_id can't be found. No matter whether it
+ // is found or not, we still end up with the now-current
+ // frame selected. Warning in lookup_selected_frame in this
+ // case seems pointless.
+
+ Also get_frame_id may access the target's registers/memory,
+ and thus skipping get_frame_id optimizes the common case.
+
+ Saving the selected frame this way makes get_selected_frame
+ and restore_current_frame return/re-select whatever frame is
+ the innermost (current) then. */
+ selected_frame_level = -1;
+ selected_frame_id = null_frame_id;
+ }
+ else
+ selected_frame_id = get_frame_id (fi);
+
/* NOTE: cagney/2002-05-04: FI can be NULL. This occurs when the
frame is being invalidated. */
diff --git a/gdb/frame.h b/gdb/frame.h
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -186,8 +186,14 @@ class scoped_restore_selected_frame
private:
- /* The ID of the previously selected frame. */
+ /* The ID and level of the previously selected frame. */
struct frame_id m_fid;
+ int m_level;
+
+ /* Save/restore the language as well, because selecting a frame
+ changes the current language to the frame's language if "set
+ language auto". */
+ enum language m_lang;
};
/* Methods for constructing and comparing Frame IDs. */
@@ -316,24 +322,49 @@ extern bool has_stack_frames ();
modifies the target invalidating the frame cache). */
extern void reinit_frame_cache (void);
-/* On demand, create the selected frame and then return it. If the
- selected frame can not be created, this function prints then throws
- an error. When MESSAGE is non-NULL, use it for the error message,
+/* Return the selected frame. Always returns non-NULL. If there
+ isn't an inferior sufficient for creating a frame, an error is
+ thrown. When MESSAGE is non-NULL, use it for the error message,
otherwise use a generic error message. */
/* FIXME: cagney/2002-11-28: At present, when there is no selected
frame, this function always returns the current (inner most) frame.
It should instead, when a thread has previously had its frame
selected (but not resumed) and the frame cache invalidated, find
and then return that thread's previously selected frame. */
-extern struct frame_info *get_selected_frame (const char *message);
-
-/* If there is a selected frame, return it. Otherwise, return NULL. */
-extern struct frame_info *get_selected_frame_if_set (void);
+extern struct frame_info *get_selected_frame (const char *message = nullptr);
-/* Select a specific frame. NULL, apparently implies re-select the
- inner most frame. */
+/* Select a specific frame. NULL implies re-select the inner most
+ frame. */
extern void select_frame (struct frame_info *);
+/* Save the frame ID and frame level of the selected frame in FRAME_ID
+ and FRAME_LEVEL, to be restored later with restore_selected_frame.
+
+ This is preferred over getting the same info out of
+ get_selected_frame directly because this function does not create
+ the selected-frame's frame_info object if it hasn't been created
+ yet, and thus is more efficient and doesn't throw. */
+extern void save_selected_frame (frame_id *frame_id, int *frame_level)
+ noexcept;
+
+/* Restore selected frame as saved with save_selected_frame.
+
+ Does not try to find the corresponding frame_info object. Instead
+ the next call to get_selected_frame will look it up and cache the
+ result.
+
+ This function does not throw. It is designed to be safe to called
+ from the destructors of RAII types. */
+extern void restore_selected_frame (frame_id frame_id, int frame_level)
+ noexcept;
+
+/* Lookup the frame_info object for the selected frame FRAME_ID /
+ FRAME_LEVEL and cache the result.
+
+ If FRAME_LEVEL > 0 and the originally selected frame isn't found,
+ warn and select the innermost (current) frame. */
+extern void lookup_selected_frame (frame_id frame_id, int frame_level);
+
/* Given a FRAME, return the next (more inner, younger) or previous
(more outer, older) frame. */
extern struct frame_info *get_prev_frame (struct frame_info *);
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -673,6 +673,10 @@ class scoped_restore_current_thread
frame_id m_selected_frame_id;
int m_selected_frame_level;
bool m_was_stopped;
+ /* Save/restore the language as well, because selecting a frame
+ changes the current language to the frame's language if "set
+ language auto". */
+ enum language m_lang;
};
/* Returns a pointer into the thread_info corresponding to
diff --git a/gdb/infrun.c b/gdb/infrun.c
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -9017,8 +9017,10 @@ struct infcall_control_state
enum stop_stack_kind stop_stack_dummy = STOP_NONE;
int stopped_by_random_signal = 0;
- /* ID if the selected frame when the inferior function call was made. */
+ /* ID and level of the selected frame when the inferior function
+ call was made. */
struct frame_id selected_frame_id {};
+ int selected_frame_level = -1;
};
/* Save all of the information associated with the inferior<==>gdb
@@ -9047,27 +9049,12 @@ save_infcall_control_state ()
inf_status->stop_stack_dummy = stop_stack_dummy;
inf_status->stopped_by_random_signal = stopped_by_random_signal;
- inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
+ save_selected_frame (&inf_status->selected_frame_id,
+ &inf_status->selected_frame_level);
return inf_status;
}
-static void
-restore_selected_frame (const frame_id &fid)
-{
- frame_info *frame = frame_find_by_id (fid);
-
- /* If inf_status->selected_frame_id is NULL, there was no previously
- selected frame. */
- if (frame == NULL)
- {
- warning (_("Unable to restore previously selected frame."));
- return;
- }
-
- select_frame (frame);
-}
-
/* Restore inferior session state to INF_STATUS. */
void
@@ -9095,21 +9082,8 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
if (target_has_stack)
{
- /* The point of the try/catch is that if the stack is clobbered,
- walking the stack might encounter a garbage pointer and
- error() trying to dereference it. */
- try
- {
- restore_selected_frame (inf_status->selected_frame_id);
- }
- catch (const gdb_exception_error &ex)
- {
- exception_fprintf (gdb_stderr, ex,
- "Unable to restore previously selected frame:\n");
- /* Error in restoring the selected frame. Select the
- innermost frame. */
- select_frame (get_current_frame ());
- }
+ restore_selected_frame (inf_status->selected_frame_id,
+ inf_status->selected_frame_level);
}
delete inf_status;
diff --git a/gdb/stack.c b/gdb/stack.c
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1842,9 +1842,9 @@ trailing_outermost_frame (int count)
static void
select_frame_command_core (struct frame_info *fi, bool ignored)
{
- struct frame_info *prev_frame = get_selected_frame_if_set ();
+ frame_info *prev_frame = get_selected_frame ();
select_frame (fi);
- if (get_selected_frame_if_set () != prev_frame)
+ if (get_selected_frame () != prev_frame)
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
}
@@ -1863,10 +1863,9 @@ select_frame_for_mi (struct frame_info *fi)
static void
frame_command_core (struct frame_info *fi, bool ignored)
{
- struct frame_info *prev_frame = get_selected_frame_if_set ();
-
+ frame_info *prev_frame = get_selected_frame ();
select_frame (fi);
- if (get_selected_frame_if_set () != prev_frame)
+ if (get_selected_frame () != prev_frame)
gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
else
print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
diff --git a/gdb/thread.c b/gdb/thread.c
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1325,20 +1325,26 @@ switch_to_thread (process_stratum_target *proc_target, ptid_t ptid)
switch_to_thread (thr);
}
-static void
-restore_selected_frame (struct frame_id a_frame_id, int frame_level)
+/* See frame.h. */
+
+void
+lookup_selected_frame (struct frame_id a_frame_id, int frame_level)
{
struct frame_info *frame = NULL;
int count;
- /* This means there was no selected frame. */
+ /* This either means there was no selected frame, or the selected
+ frame was the current frame. In either case, select the current
+ frame. */
if (frame_level == -1)
{
- select_frame (NULL);
+ select_frame (get_current_frame ());
return;
}
- gdb_assert (frame_level >= 0);
+ /* select_frame never saves 0 in SELECTED_FRAME_LEVEL, so we
+ shouldn't see it here. */
+ gdb_assert (frame_level > 0);
/* Restore by level first, check if the frame id is the same as
expected. If that fails, try restoring by frame id. If that
@@ -1409,64 +1415,28 @@ scoped_restore_current_thread::restore ()
&& target_has_stack
&& target_has_memory)
restore_selected_frame (m_selected_frame_id, m_selected_frame_level);
+
+ set_language (m_lang);
}
scoped_restore_current_thread::~scoped_restore_current_thread ()
{
if (!m_dont_restore)
- {
- try
- {
- restore ();
- }
- catch (const gdb_exception &ex)
- {
- /* We're in a dtor, there's really nothing else we can do
- but swallow the exception. */
- }
- }
+ restore ();
}
scoped_restore_current_thread::scoped_restore_current_thread ()
{
m_inf = inferior_ref::new_reference (current_inferior ());
+ m_lang = current_language->la_language;
+
if (inferior_ptid != null_ptid)
{
m_thread = thread_info_ref::new_reference (inferior_thread ());
- struct frame_info *frame;
-
m_was_stopped = m_thread->state == THREAD_STOPPED;
- if (m_was_stopped
- && target_has_registers
- && target_has_stack
- && target_has_memory)
- {
- /* When processing internal events, there might not be a
- selected frame. If we naively call get_selected_frame
- here, then we can end up reading debuginfo for the
- current frame, but we don't generally need the debuginfo
- at this point. */
- frame = get_selected_frame_if_set ();
- }
- else
- frame = NULL;
-
- try
- {
- m_selected_frame_id = get_frame_id (frame);
- m_selected_frame_level = frame_relative_level (frame);
- }
- catch (const gdb_exception_error &ex)
- {
- m_selected_frame_id = null_frame_id;
- m_selected_frame_level = -1;
-
- /* Better let this propagate. */
- if (ex.error == TARGET_CLOSE_ERROR)
- throw;
- }
+ save_selected_frame (&m_selected_frame_id, &m_selected_frame_level);
}
}

View File

@ -0,0 +1,169 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Sat, 31 Oct 2020 00:27:18 +0000
Subject: gdb-rhbz1909902-frame_id_p-assert-2.patch
;; Backport patch #2 which fixes a frame_id_p assertion failure (RH BZ 1909902).
Fix frame cycle detection
The recent commit to make scoped_restore_current_thread's cdtors
exception free regressed gdb.base/eh_return.exp:
Breakpoint 1, 0x00000000004012bb in eh2 (gdb/frame.c:641: internal-error: frame_id get_frame_id(frame_info*): Assertion `stashed' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.base/eh_return.exp: hit breakpoint (GDB internal error)
That testcase uses __builtin_eh_return and, before the regression, the
backtrace at eh2 looked like this:
(gdb) bt
#0 0x00000000004006eb in eh2 (p=0x4006ec <continuation>) at src/gdb/testsuite/gdb.base/eh_return.c:54
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
That "previous frame identical to this frame" is caught by the cycle
detection based on frame id.
The assertion failing is this one:
638 /* Since this is the first frame in the chain, this should
639 always succeed. */
640 bool stashed = frame_stash_add (fi);
641 gdb_assert (stashed);
originally added by
commit f245535cf583ae4ca13b10d47b3c7d3334593ece
Author: Pedro Alves <palves@redhat.com>
AuthorDate: Mon Sep 5 18:41:38 2016 +0100
Fix PR19927: Avoid unwinder recursion if sniffer uses calls parse_and_eval
The assertion is failing because frame #1's frame id was stashed
before the id of frame #0 is stashed. The frame id of frame #1 was
stashed here:
(top-gdb) bt
#0 frame_stash_add (frame=0x1e24c90) at src/gdb/frame.c:276
#1 0x0000000000669c1b in get_prev_frame_if_no_cycle (this_frame=0x19f8370) at src/gdb/frame.c:2120
#2 0x000000000066a339 in get_prev_frame_always_1 (this_frame=0x19f8370) at src/gdb/frame.c:2303
#3 0x000000000066a360 in get_prev_frame_always (this_frame=0x19f8370) at src/gdb/frame.c:2319
#4 0x000000000066b56c in get_frame_unwind_stop_reason (frame=0x19f8370) at src/gdb/frame.c:3028
#5 0x000000000059f929 in dwarf2_frame_cfa (this_frame=0x19f8370) at src/gdb/dwarf2/frame.c:1462
#6 0x00000000005ce434 in dwarf_evaluate_loc_desc::get_frame_cfa (this=0x7fffffffc070) at src/gdb/dwarf2/loc.c:666
#7 0x00000000005989a9 in dwarf_expr_context::execute_stack_op (this=0x7fffffffc070, op_ptr=0x1b2a053 "\364\003", op_end=0x1b2a053 "\364\003") at src/gdb/dwarf2/expr.c:1161
#8 0x0000000000596af6 in dwarf_expr_context::eval (this=0x7fffffffc070, addr=0x1b2a052 "\234\364\003", len=1) at src/gdb/dwarf2/expr.c:303
#9 0x0000000000597b4e in dwarf_expr_context::execute_stack_op (this=0x7fffffffc070, op_ptr=0x1b2a063 "", op_end=0x1b2a063 "") at src/gdb/dwarf2/expr.c:865
#10 0x0000000000596af6 in dwarf_expr_context::eval (this=0x7fffffffc070, addr=0x1b2a061 "\221X", len=2) at src/gdb/dwarf2/expr.c:303
#11 0x00000000005c8b5a in dwarf2_evaluate_loc_desc_full (type=0x1b564d0, frame=0x19f8370, data=0x1b2a061 "\221X", size=2, per_cu=0x1b28760, per_objfile=0x1a84930, subobj_type=0x1b564d0, subobj_byte_offset=0) at src/gdb/dwarf2/loc.c:2260
#12 0x00000000005c9243 in dwarf2_evaluate_loc_desc (type=0x1b564d0, frame=0x19f8370, data=0x1b2a061 "\221X", size=2, per_cu=0x1b28760, per_objfile=0x1a84930) at src/gdb/dwarf2/loc.c:2444
#13 0x00000000005cb769 in locexpr_read_variable (symbol=0x1b59840, frame=0x19f8370) at src/gdb/dwarf2/loc.c:3687
#14 0x0000000000663137 in language_defn::read_var_value (this=0x122ea60 <c_language_defn>, var=0x1b59840, var_block=0x0, frame=0x19f8370) at src/gdb/findvar.c:618
#15 0x0000000000663c3b in read_var_value (var=0x1b59840, var_block=0x0, frame=0x19f8370) at src/gdb/findvar.c:822
#16 0x00000000008c7d9f in read_frame_arg (fp_opts=..., sym=0x1b59840, frame=0x19f8370, argp=0x7fffffffc470, entryargp=0x7fffffffc490) at src/gdb/stack.c:542
#17 0x00000000008c89cd in print_frame_args (fp_opts=..., func=0x1b597c0, frame=0x19f8370, num=-1, stream=0x1aba860) at src/gdb/stack.c:890
#18 0x00000000008c9bf8 in print_frame (fp_opts=..., frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, print_args=1, sal=...) at src/gdb/stack.c:1394
#19 0x00000000008c92b9 in print_frame_info (fp_opts=..., frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, print_args=1, set_current_sal=1) at src/gdb/stack.c:1119
#20 0x00000000008c75f0 in print_stack_frame (frame=0x19f8370, print_level=0, print_what=SRC_AND_LOC, set_current_sal=1) at src/gdb/stack.c:366
#21 0x000000000070250b in print_stop_location (ws=0x7fffffffc9e0) at src/gdb/infrun.c:8110
#22 0x0000000000702569 in print_stop_event (uiout=0x1a8b9e0, displays=true) at src/gdb/infrun.c:8126
#23 0x000000000096d04b in tui_on_normal_stop (bs=0x1bcd1c0, print_frame=1) at src/gdb/tui/tui-interp.c:98
...
Before the commit to make scoped_restore_current_thread's cdtors
exception free, scoped_restore_current_thread's dtor would call
get_frame_id on the selected frame, and we use
scoped_restore_current_thread pervasively. That had the side effect
of stashing the frame id of frame #0 before reaching the path shown in
the backtrace. I.e., the frame id of frame #0 happened to be stashed
before the frame id of frame #1. But that was by chance, not by
design.
This commit:
commit 256ae5dbc73d1348850f86ee77a0dc3b04bc7cc0
Author: Kevin Buettner <kevinb@redhat.com>
AuthorDate: Mon Oct 31 12:47:42 2016 -0700
Stash frame id of current frame before stashing frame id for previous frame
Fixed a similar problem, by making sure get_prev_frame computes the
frame id of the current frame before unwinding the previous frame, so
that the cycle detection works properly. That fix misses the scenario
we're now running against, because if you notice, the backtrace above
shows that frame #4 calls get_prev_frame_always, not get_prev_frame.
I.e., nothing is calling get_frame_id on the current frame.
The fix here is to move Kevin's fix down from get_prev_frame to
get_prev_frame_always. Or actually, a bit further down to
get_prev_frame_always_1 -- note that inline_frame_this_id calls
get_prev_frame_always, so we need to be careful to avoid recursion in
that scenario.
gdb/ChangeLog:
* frame.c (get_prev_frame): Move get_frame_id call from here ...
(get_prev_frame_always_1): ... to here.
* inline-frame.c (inline_frame_this_id): Mention
get_prev_frame_always_1 in comment.
Change-Id: Id960c98ab2d072c48a436c3eb160cc4b2a5cfd1d
diff --git a/gdb/frame.c b/gdb/frame.c
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2133,6 +2133,23 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
if (get_frame_type (this_frame) == INLINE_FRAME)
return get_prev_frame_if_no_cycle (this_frame);
+ /* If this_frame is the current frame, then compute and stash its
+ frame id prior to fetching and computing the frame id of the
+ previous frame. Otherwise, the cycle detection code in
+ get_prev_frame_if_no_cycle() will not work correctly. When
+ get_frame_id() is called later on, an assertion error will be
+ triggered in the event of a cycle between the current frame and
+ its previous frame.
+
+ Note we do this after the INLINE_FRAME check above. That is
+ because the inline frame's frame id computation needs to fetch
+ the frame id of its previous real stack frame. I.e., we need to
+ avoid recursion in that case. This is OK since we're sure the
+ inline frame won't create a cycle with the real stack frame. See
+ inline_frame_this_id. */
+ if (this_frame->level == 0)
+ get_frame_id (this_frame);
+
/* Check that this frame is unwindable. If it isn't, don't try to
unwind to the prev frame. */
this_frame->stop_reason
@@ -2410,16 +2427,6 @@ get_prev_frame (struct frame_info *this_frame)
something should be calling get_selected_frame() or
get_current_frame(). */
gdb_assert (this_frame != NULL);
-
- /* If this_frame is the current frame, then compute and stash
- its frame id prior to fetching and computing the frame id of the
- previous frame. Otherwise, the cycle detection code in
- get_prev_frame_if_no_cycle() will not work correctly. When
- get_frame_id() is called later on, an assertion error will
- be triggered in the event of a cycle between the current
- frame and its previous frame. */
- if (this_frame->level == 0)
- get_frame_id (this_frame);
frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -161,7 +161,8 @@ inline_frame_this_id (struct frame_info *this_frame,
real frame's this_id method. So we must call
get_prev_frame_always. Because we are inlined into some
function, there must be previous frames, so this is safe - as
- long as we're careful not to create any cycles. */
+ long as we're careful not to create any cycles. See related
+ comments in get_prev_frame_always_1. */
*this_id = get_frame_id (get_prev_frame_always (this_frame));
/* We need a valid frame ID, so we need to be based on a valid

View File

@ -37,7 +37,7 @@ Version: 10.1
# The release always contains a leading reserved number, start it at 1.
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
Release: 2.0.riscv64%{?dist}
Release: 4.0.riscv64%{?dist}
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL
# Do not provide URL for snapshots as the file lasts there only for 2 days.
@ -189,7 +189,7 @@ Source5: %{libstdcxxpython}.tar.xz
Source6: gdbtui
# libipt: Intel Processor Trace Decoder Library
%global libipt_version 2.0.2
%global libipt_version 2.0.4
#=fedora
Source7: v%{libipt_version}.tar.gz
#=fedora
@ -1184,10 +1184,17 @@ fi
%endif
%changelog
* Thu Nov 26 2020 David Abdurachmanov <david.abdurachmanov@sifive.com> - 10.1-2.0.riscv64
* Fri May 21 2021 David Abdurachmanov <david.abdurachmanov@gmail.com> - 10.1-4.0.riscv64
- Add riscv64-linux-gnu to enabled targets
- Disable inprocess agent for riscv64
* Thu Mar 11 2021 Kevin Buettner <kevinb@redhat.com> - 10.1-4
- Update libipt to version 2.0.4.
* Fri Mar 05 2021 Kevin Buettner <kevinb@redhat.com> - 10.1-3
- Backport patches which fix frame_id_p assertion failure (RHBZ 1909902,
Pedro Alves).
* Wed Nov 04 2020 Kevin Buettner <kevinb@redhat.com> - 10.1-2
- Fix bug in local patch gdb-6.6-buildid-locate.patch which prevented
debuginfod from working.

View File

@ -1,3 +1,3 @@
SHA512 (gdb-libstdc++-v3-python-8.1.1-20180626.tar.xz) = a8b1c54dd348cfeb37da73f968742896be3dd13a4215f8d8519870c2abea915f5176c3fa6989ddd10f20020a16f0fab20cbae68ee8d58a82234d8778023520f8
SHA512 (v2.0.2.tar.gz) = bc256a57a8481e0be8220624da3ccf1fe4bf0ea83e9808fdf0aad6db865aee402a36e78285efb0316c016f57e0d6fc56b647ee8e9a2ad4b05bfc1ad68ddde535
SHA512 (gdb-10.1.tar.xz) = 0dc54380435c6853db60f1e388b94836d294dfa9ad7f518385a27db4edd03cb970f8717d5f1e9c9a0d4a33d7fcf91bc2e5d6c9cf9e4b561dcc74e65b806c1537
SHA512 (v2.0.4.tar.gz) = 596d2dac25fdbd3e5660d7e1feeb7e8d5d359d1d0e19b62ef593449037df236db1d4d98820f0031061b5573ed67797a85a77fb9991e215abaabc4bfe16ceaec8