[Bug libgcc/89714] New: allow for overriding the thread-detection mechanism
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89714 Bug ID: 89714 Summary: allow for overriding the thread-detection mechanism Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libgcc Assignee: unassigned at gcc dot gnu.org Reporter: tneumann at users dot sourceforge.net Target Milestone: --- Currently the libgcc code uses a weak symbol to recognize if the program is linked again pthreads (in __gthread_active_p()), and switches between implementations at runtime based the presence of the weak symbol. But if we know statically that we will always run multi-threaded, this dynamic dispatch is quite wasteful. This is particular visible for std C++ classes that indirectly inline this code, for example std::shared_ptr. When copying a std::shared_ptr this check is performed twice, each time with two code paths. If we force __gthread_active_p to always return true the assembler code is quite a bit shorter (and has less branches and executes less instructions, of course). This can be seen with the quick hack here https://godbolt.org/z/946lzO Changing the first line to #if 1 reduces the generated code significantly. It would be good to offer a similar mechanism without having to resort to horrible hacks.
[Bug libgcc/89714] allow for overriding the thread-detection mechanism
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89714 --- Comment #3 from Thomas Neumann --- Perhaps the header files could be changed to react to _REENTRANT, as that seems to be the define that is set by gcc when requesting threading support. The redundant checks within the shared library are less of an issue. Of course they waste a few cycles, too, but the unnecessary checks in the header files are far worse as they are inlined all over the place when using, e.g., shared_ptr.
[Bug libgcc/107026] [13 Regression] gcc_assert (in_shutdown || ob); build failure for i586-msdosdjgpp target
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107026 --- Comment #6 from Thomas Neumann --- I have a patch ready, I am waiting for approval: https://gcc.gnu.org/pipermail/gcc-patches/2022-September/602130.html When using the atomic fast path deregistering can fail during program shutdown if the lookup structures are already destroyed. The assert in __deregister_frame_info_bases takes that into account. In the non-fast-path case however is not aware of program shutdown, which caused a compiler error on such platforms. We fix that by introducing a constant for in_shutdown in non-fast-path builds. libgcc/ChangeLog: * unwind-dw2-fde.c: Introduce a constant for in_shutdown for the non-fast-path case. --- libgcc/unwind-dw2-fde.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c index d237179f4ea..0bcd5061d76 100644 --- a/libgcc/unwind-dw2-fde.c +++ b/libgcc/unwind-dw2-fde.c @@ -67,6 +67,8 @@ static void init_object (struct object *ob); #else +/* Without fast path frame deregistration must always succeed. */ +static const int in_shutdown = 0; /* The unseen_objects list contains objects that have been registered but not yet categorized in any way. The seen_objects list has had -- 2.34.1
[Bug libgcc/107026] [13 Regression] gcc_assert (in_shutdown || ob); build failure for i586-msdosdjgpp target
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107026 --- Comment #9 from Thomas Neumann --- Yes, commit 386ebf75f4c0342b1f823f4e4aba07abda3288d1 fixes the assert.
[Bug libgcc/107675] [13 Regression] GCC-13 is significantly slower to startup on C++ statically linked programs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107675 --- Comment #15 from Thomas Neumann --- > You cannot use 'relaxed' atomic load in is_object_initialized - as thread > performing such load will not observe/synchronize with any modifications > (other than atomic variable itself) performed by other threads. you are right, this has to be acquire. Very unfortunate. I thought we would get away with relaxed because we double-check anyway, but with relaxed we might miss the writes to the other fields of object. On systems with strong memory order it does not matter, but on ARM this will make the check slower.
[Bug libgcc/107675] [13 Regression] GCC-13 is significantly slower to startup on C++ statically linked programs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107675 --- Comment #16 from Thomas Neumann --- I have committed a fix: commit 6e56633daae79f514b0e71f4d9849bcd8d9ce71f Author: Thomas Neumann Date: Fri Dec 9 18:23:44 2022 +0100 initialize fde objects lazily When registering an unwind frame with __register_frame_info_bases we currently initialize that fde object eagerly. This has the advantage that it is immutable afterwards and we can safely access it from multiple threads, but it has the disadvantage that we pay the initialization cost even if the application never throws an exception. This commit changes the logic to initialize the objects lazily. The objects themselves are inserted into the b-tree when registering the frame, but the sorted fde_vector is not constructed yet. Only on the first time that an exception tries to pass through the registered code the object is initialized. We notice that with a double checking, first doing a relaxed load of the sorted bit and then re-checking under a mutex when the object was not initialized yet. Note that the check must implicitly be safe concering a concurrent frame deregistration, as trying the deregister a frame that is on the unwinding path of a concurrent exception is inherently racy. libgcc/ChangeLog: * unwind-dw2-fde.c: Initialize fde object lazily when the first exception tries to pass through.
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 --- Comment #4 from Thomas Neumann --- It looks like the code does not find an unwind frame when de-registering an exception handler. Are you sure that you do not de-register a dynamic frame twice? Otherwise I would need a way to reproduce the problem, ideally with a binary. I am also fine with remote access if that is easier for you. Or if that is not possible you might want to add printf calls to btree_insert and btree_remove, tracing their call arguments. Having such a tracer should allow us to reproduce the problem even without the host program. (And it would allow for detecting duplicate de-registrations, i.e., errors in the host program. I had that problem in the past myself with JITed code).
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 --- Comment #7 from Thomas Neumann --- Is it correct that in your case range[0]
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 --- Comment #9 from Thomas Neumann --- I will check how we can handle such a situation. But how did this happen to begin with? Is this regular code or did you do anything special? I am puzzled how the unwinding table can be placed like that.
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 --- Comment #11 from Thomas Neumann --- Created attachment 57669 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57669&action=edit patch to handle overlapping ranges Does this patch fix the problem for you? I think it should, but I would really like to have a reproducer to make sure.
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 Thomas Neumann changed: What|Removed |Added Attachment #57669|0 |1 is obsolete|| --- Comment #14 from Thomas Neumann --- Created attachment 57675 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57675&action=edit updated patch updated patch without single line blocks
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 Thomas Neumann changed: What|Removed |Added Attachment #57675|0 |1 is obsolete|| --- Comment #15 from Thomas Neumann --- Created attachment 57679 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57679&action=edit fixed patch Can you please try the updated patch? I had accidentally dropped an if nesting level when trying to adhere to the gcc style, sorry for that.
[Bug libgcc/111731] [13/14 regression] gcc_assert is hit at libgcc/unwind-dw2-fde.c#L291
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731 Thomas Neumann changed: What|Removed |Added Attachment #57679|0 |1 is obsolete|| --- Comment #18 from Thomas Neumann --- Created attachment 57692 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57692&action=edit patch with separate btrees We will have to do that, I have updated the patch to use a separate lookup structure for the tables. Which prevents the original problem and hopefully fixes the issue. The only thing that makes me nervous is that if some JITer comes up with the idea of placing an unwind tuple inside some code range, what prevents them from placing code from one table within code from another table? Which would break the assumption that code ranges do not overlap. Note that the non-fast-path code also makes the assumption that code ranges do not overlap, see the comment in _Unwind_Find_FDE. Thus perhaps no JIT code emitter will do that. But if somebody does we should probably store the fde instead of the object inside the lookup structure. The fde ranges really must not overlap, otherwise everything breaks. But I would like to not do that because we have more fdes than objects and storing each fde individually would make frame registration more expensive (even though lookup became faster, because we would no longer have to traverse the object).
[Bug libgcc/109685] [13/14 Regression] Memory leak in `__deregister_frame`
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109685 --- Comment #6 from Thomas Neumann --- > GCC 13.2 is being released, retargeting bugs to GCC 13.3. the bug should be closed as fixed, the bug fix is already in the 13.2 branch. (I do not have permissions to do that, though).
[Bug libgcc/110956] gcc_assert is hit at gcc-13.2.0/libgcc/unwind-dw2-fde.c#L291 with some special library
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110956 --- Comment #1 from Thomas Neumann --- The assert says that the code tries to de-register a frame that it did not register before or that was deregistered before. If you see that failing you might want to add some print statements to __register_frame_info_{tables_|}bases and __deregister_frame_info_bases. But the example that you included in the report does not seem to trigger the assert but crashes during unwinding instead? This has to be looked at in a debugger. I do not have access to Solaris. If you can give me remote access to a suitable machine I am willing to debug this, otherwise you must check yourself why the crash happens.
[Bug libgcc/110955] SIGSEGV in libgcc_s.so.1`classify_object_over_fdes+0x140 on Solaris SPARC with GCC 13 runtime
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110955 --- Comment #4 from Thomas Neumann --- I am not sure what caused that, but in GCC 13 the unwinding logic now looks into the table when registering the frame, while previously the table was only inspected on the first exception. Which means we might notice invalid tables earlier.
[Bug libgcc/110956] [13/14 regression] gcc_assert is hit at gcc-13.2.0/libgcc/unwind-dw2-fde.c#L291 with some special library
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110956 --- Comment #5 from Thomas Neumann --- The assert itself is old, it was just updated due to code changes. And asserting there makes sense, if we keep an old frame around we might see a crash later during unwinding if the unwinder tries to access code that does no longer exist due to dlclose. This does not apply if the bug is in the program itself, of course, but I think it is more probable that it is a bug in gcc. If somebody has a VM image or a remote machine I can use I would be happy to debug the problem myself, but I do not have access to Solaris.
[Bug libgcc/110956] [13/14 regression] gcc_assert is hit at gcc-13.2.0/libgcc/unwind-dw2-fde.c#L291 with some special library
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110956 --- Comment #7 from Thomas Neumann --- Thanks for the pointer, I could reproduce the problem in a VM now. That shared library uses an usual table encoding that has to reference the original base pointer within get_pc_range. But when deregistering a frame we simply set the base pointer to nullptr, which does not work here. I will write a patch that makes sure we always have to correct base pointer available.
[Bug libgcc/110956] [13/14 regression] gcc_assert is hit at gcc-13.2.0/libgcc/unwind-dw2-fde.c#L291 with some special library
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110956 --- Comment #8 from Thomas Neumann --- Created attachment 55715 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55715&action=edit patch to use the correct base pointer The attached patch fixes the test case by using the correct base pointer during frame deregistration.
[Bug libgcc/109685] [13/14 Regression] Memory leak in `__deregister_frame`
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109685 --- Comment #1 from Thomas Neumann --- Created attachment 54969 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54969&action=edit fix for the issue
[Bug libgcc/109685] [13/14 Regression] Memory leak in `__deregister_frame`
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109685 --- Comment #2 from Thomas Neumann --- I can reproduce the issue. The attached patch fixes the problem, I will send it for reviewing.
[Bug libgcc/109670] Exception handling broken for 32bit Windows starting with GCC 13
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109670 --- Comment #8 from Thomas Neumann --- Do you by chance an Ada-enabled WIN32 toolchain somewhere that I can use to build gcc with? Or an script on how to do that? I have not managed to reproduce the problem yet, unfortunately, because I could not build Ada.
[Bug libgcc/109670] Exception handling broken for 32bit Windows starting with GCC 13
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109670 --- Comment #10 from Thomas Neumann --- (In reply to LIU Hao from comment #9) > GDB is affected, too: I will debug that. That is easier to build than Ada. Strange that it only affects 32bit Windows. I will take a look.
[Bug libgcc/109670] [13/14 regression] Exception handling broken for 32-bit Windows
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109670 --- Comment #12 from Thomas Neumann --- Created attachment 55037 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55037&action=edit radix sort fix I could reproduce the problem, the radix sort did not behave correctly when we ran out of bits, which can happen on 32bit platforms. The attached patch fixes the problem.
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 --- Comment #14 from Thomas Neumann --- I cannot reproduce the problem, but admittedly I used a newer Ubuntu version. I tried compiling it with gcc 7.5.0, linking it with gold 1.16, and using the gcc version you specified (07c52d1eec9) for the shared library without problems. Can you attach the a.out that you generate? This will hopefully allow me to reproduce the problem.
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 Thomas Neumann changed: What|Removed |Added CC||fweimer at redhat dot com --- Comment #16 from Thomas Neumann --- e724b04
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 --- Comment #17 from Thomas Neumann --- The bug was introduced by gcc commit e724b04. It avoids calls to read_encoded_value_with_base for performance reasons, but unfortunately this causes the variable eh_frame to be uninitialized if the fast path is taken in find_fde_tail (unwind-dw2-fde-dip.c). This is only visible with the gold linker because gold does not provide a conveniently organized unwind table, with causes the code to fall back to the slow linear_search_fdes, which uses the (uninitialized) eh_frame value. Florian, can you fix that? For me it is not obvious how to compute the correct eh_frame value without calling read_encoded_value_with_base, but you probably know how to do that.
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 --- Comment #19 from Thomas Neumann --- Hm, then I don't know how we end up with the non-regular table content. The code checks for hdr->fde_count_enc != DW_EH_PE_omit, and that is false in the executable that you provided. But regardless of why the table is strange, the bug is definitively caused by the uninitialized eh_frame variable in find_fde_tail. It must be set in the fast path, too.
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 --- Comment #21 from Thomas Neumann --- It must be something more complex. value is small here (more precisely: 1888 in the crashes later), which is not a valid pointer address. We probably have to add this to some base pointer? But it is not obvious to me to which one.
[Bug libgcc/109712] Segmentation fault in linear_search_fdes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109712 --- Comment #26 from Thomas Neumann --- (In reply to Florian Weimer from comment #23) > > u is the original read pointer as far as I can see. So it looks like it > should look like this: > > diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c > index 6223f5f18a2..5a6352227cc 100644 > --- a/libgcc/unwind-dw2-fde-dip.c > +++ b/libgcc/unwind-dw2-fde-dip.c > @@ -403,8 +403,8 @@ find_fde_tail (_Unwind_Ptr pc, >BFD ld generates. */ >signed value __attribute__ ((mode (SI))); >memcpy (&value, p, sizeof (value)); > + eh_frame = p + value >p += sizeof (value); > - dbase = value; /* No adjustment because pcrel has base 0. */ > } >else > p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc, that seems to be correct, the test case succeeds with that patch.
[Bug libgcc/109670] [13/14 regression] Exception handling broken for 32-bit Windows
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109670 --- Comment #19 from Thomas Neumann --- I think we can close this bug as fixed, but I do not have permissions to do that.