public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix assertion for unwind-dw2-fde.c btree changes
@ 2023-05-14 16:09 Sören Tempel
  2023-05-14 18:59 ` Thomas Neumann
  0 siblings, 1 reply; 10+ messages in thread
From: Sören Tempel @ 2023-05-14 16:09 UTC (permalink / raw)
  To: neumann; +Cc: gcc-patches, tneumann, alice

[-- Attachment #1: Type: text/plain, Size: 4764 bytes --]

Dear Thomas Neumann,

I am contacting you as the author of the commit with commit hash
6e80a1d164d1f996ad08a512c000025a7c2ca893 [1] in the GCC repository. In
this commit, you refactored the __register_frame/__deregister_frame
implementation in GCC. The commit is part of the GCC 13 release.
While upgrading the GCC version in Alpine Linux from GCC 12 to GCC 13
we ran into a regression introduced by these changes. The regression
manifests itself in a failing assertion in __deregister_frame_info_bases.
The assertion failure was observed while using Chromium's `flatc` build
system tool. The failing assertion is:

	unwind-dw2-fde.c:281	gcc_assert (in_shutdown || ob);

The assertion fails for us because ob is a null pointer and in_shutdown
is zero. The backtrace for the assertion failure looks as follows:

	#0  __restore_sigs (set=set@entry=0x7fffffffe050) at ./arch/x86_64/syscall_arch.h:40
	#1  0x00007ffff7facea5 in raise (sig=sig@entry=6) at src/signal/raise.c:11
	#2  0x00007ffff7f7ffa8 in abort () at src/exit/abort.c:11
	#3  0x00007ffff7f3d411 in __deregister_frame_info_bases (begin=0x55555557ef58)
	    at /home/buildozer/aports/main/gcc/src/gcc-13-20230506/libgcc/unwind-dw2-fde.c:281
	#4  __deregister_frame_info_bases (begin=0x55555557ef58)
	    at /home/buildozer/aports/main/gcc/src/gcc-13-20230506/libgcc/unwind-dw2-fde.c:219
	#5  0x0000555555580072 in __do_global_dtors_aux ()
	#6  0x000000185eb03fee in ?? ()
	#7  0x00007ffff7fc1ad6 in __libc_exit_fini () at ldso/dynlink.c:1453
	#8  0x00007ffff7f78082 in exit (code=1) at src/exit/exit.c:30
	#9  0x00005555555802a6 in Error(flatbuffers::FlatCompiler const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, bool) ()
	#10 0x000055555560f952 in flatbuffers::FlatCompiler::ParseFromCommandLineArguments(int, char const**) ()
	#11 0x0000555555581b42 in main (

I noticed that you already pushed a fixup for the aforementioned
assertion in commit 386ebf75f4c0342b1f823f4e4aba07abda3288d1 [2].
However, I believe there is one more edge case that isn't being account
for presently: If the inserted entry has a size of 0 (i.e. if range[1] -
range[0] == 0) then the btree_insert call in __register_frame_info_bases
will not insert anything. This is not accounted for in
__deregister_frame_info_bases as it is assumed that the prior
btree_insert call in __register_frame_info_bases always inserted
something into the lookup data structure.

Based on the information contained in the backtrace shown above, this
behavior can be observed in the following gdb debug session:

	(gdb) break __register_frame_info_bases if begin==0x55555557ef58
	(gdb) run
	Breakpoint 11.1, __register_frame_info_bases (begin=0x55555557ef58, ob=0x555555907f60 <object>, tbase=0x0, dbase=0x0)
	    at /home/buildozer/aports/main/gcc/src/gcc-13-20230506/libgcc/unwind-dw2-fde.c:111
	(gdb) break btree_insert
	(gdb) cont
	Continuing.
	Breakpoint 12, btree_insert (base=0, size=0, ob=0x555555907f60 <object>, t=0x7ffff7f5d290 <registered_frames>)
		at /home/buildozer/aports/main/gcc/src/gcc-13-20230506/libgcc/unwind-dw2-btree.h:726
	726       if (!size)
	(gdb) p size
	$1 = 0
	(gdb) next
	727         return false;

From the above debug output, we can deduce that nothing was inserted into
the lookup data structure for the frame beginning at 0x55555557ef58
because the size of the range is zero. If we set at breakpoint in
__deregister_frame_info_bases for the same frame we can observe the
following:

	(gdb) break __deregister_frame_info_bases if begin==0x55555557ef58
	Continuing.
	/home/buildozer/aports/community/chromium/src/chromium-113.0.5672.92/out/bld/flatc:
	Breakpoint 13.1, __deregister_frame_info_bases (begin=0x55555557ef58)
	    at /home/buildozer/aports/main/gcc/src/gcc-13-20230506/libgcc/unwind-dw2-fde.c:220
	(gdb) break unwind-dw2-fde.c:242
	(gdb) cont
	242       ob = btree_remove (&registered_frames, range[0]);
	(gdb) p range
	$2 = {0, 0}
	(gdb) next
	(gdb) p ob
	$3 = 0x0

Naturally, since nothing was inserted into the lookup data structure for
this frame, btree_remove isn't able to remove anything and returns a
null pointer for ob. This then causes the aforementioned assertion
failure.

A git-format-patch(1) for the assertion is attached, which adds handling
for the edge case that nothing was inserted via btree_insert in
__register_frame_info_bases to __deregister_frame_info_bases.

Would be cool if this could be fixed on the GCC trunk.

Greetings
Sören Tempel

[1]: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=6e80a1d164d1f996ad08a512c000025a7c2ca893
[2]: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=386ebf75f4c0342b1f823f4e4aba07abda3288d1


[-- Attachment #2: 0001-fix-assert-in-__deregister_frame_info_bases.patch --]
[-- Type: text/plain, Size: 1548 bytes --]

From 6dc56564cad69a26595cc38956355e5be7d2c2b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net>
Date: Sun, 14 May 2023 19:30:21 +0200
Subject: [PATCH] fix assert in __deregister_frame_info_bases
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The assertion in __deregister_frame_info_bases assumes that for every
frame something was inserted into the lookup data structure by
__register_frame_info_bases. Unfortunately, this does not necessarily
hold true as the btree_insert call in __register_frame_info_bases will
not insert anything for empty ranges. Therefore, we need to explicitly
account for such empty ranges in the assertion as `ob` will be a null
pointer for such ranges, hence causing the assertion to fail.

Signed-off-by: Sören Tempel <soeren@soeren-tempel.net>
---
 libgcc/unwind-dw2-fde.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index 7b74c391ced..8683a65aa02 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -278,7 +278,9 @@ __deregister_frame_info_bases (const void *begin)
   __gthread_mutex_unlock (&object_mutex);
 #endif
 
-  gcc_assert (in_shutdown || ob);
+  // If we didn't find anything in the lookup data structures then they
+  // were either already destroyed or we tried to remove an empty range.
+  gcc_assert (in_shutdown || ((range[1] - range[0]) == 0 || ob));
   return (void *) ob;
 }
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-05-15 13:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-14 16:09 [PATCH] Fix assertion for unwind-dw2-fde.c btree changes Sören Tempel
2023-05-14 18:59 ` Thomas Neumann
2023-05-14 19:52   ` alice
2023-05-14 22:35     ` Thomas Neumann
2023-05-14 23:09       ` alice
2023-05-15  7:59   ` Richard Biener
2023-05-15 12:52     ` Kyrylo Tkachov
2023-05-15 13:05       ` Thomas Neumann
2023-05-15 13:28         ` Kyrylo Tkachov
2023-05-15 13:31         ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).