Summary: | Can't insert internal breakpoints after inferior dlclose some share objects | ||
---|---|---|---|
Product: | gdb | Reporter: | Guinevere Larsen <guinevere> |
Component: | breakpoints | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | NEW --- | ||
Severity: | normal | CC: | aburgess, ssbssa, tromey, woodard |
Priority: | P2 | ||
Version: | HEAD | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Guinevere Larsen
2024-08-13 13:16:07 UTC
Does dlmopen(LM_ID_NEWLM) load a 2nd CRT in this case? Because some time ago I noticed a very similar looking problem on Windows if I load & unload a 2nd CRT. Using this example: ``` #include <windows.h> #include <stdio.h> int main() { HMODULE mod = LoadLibrary ("ucrtbase.dll"); FreeLibrary (mod); printf ("hi\n"); return 0; } ``` This happens when I step through it: ``` C:\src\tests>gdb64 gdb-32079.exe Reading symbols from gdb-32079.exe... (gdb) start Temporary breakpoint 1 at 0x140001581: file gdb-32079.c, line 6. Starting program: C:\src\tests\gdb-32079.exe Temporary breakpoint 1, main () at gdb-32079.c:6 6 HMODULE mod = LoadLibrary ("ucrtbase.dll"); (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00000000777b1000 0x00000000779584e0 Yes (*) C:\Windows\SYSTEM32\ntdll.dll 0x0000000077691000 0x00000000777aeab8 Yes (*) C:\Windows\system32\kernel32.dll 0x000007fefd691000 0x000007fefd6fb13c Yes (*) C:\Windows\system32\KernelBase.dll 0x000007feff6d1000 0x000007feff76e4bc Yes (*) C:\Windows\system32\msvcrt.dll (*): Shared library is missing debugging information. (gdb) maint info breakpoints Num Type Disp Enb Address What -4 longjmp master keep n 0x0000000077800fa0 <ntdll!longjmp> inf 1 -4.1 y- 0x0000000077800fa0 <ntdll!longjmp> inf 1 -5 longjmp master keep n 0x000007feff6de540 <msvcrt!longjmp> inf 1 -5.1 y- 0x000007feff6de540 <msvcrt!longjmp> inf 1 (gdb) n 7 FreeLibrary (mod); (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00000000777b1000 0x00000000779584e0 Yes (*) C:\Windows\SYSTEM32\ntdll.dll 0x0000000077691000 0x00000000777aeab8 Yes (*) C:\Windows\system32\kernel32.dll 0x000007fefd691000 0x000007fefd6fb13c Yes (*) C:\Windows\system32\KernelBase.dll 0x000007feff6d1000 0x000007feff76e4bc Yes (*) C:\Windows\system32\msvcrt.dll 0x000007fee6b11000 0x000007fee6c01b04 Yes (*) C:\Windows\system32\ucrtbase.dll 0x000007fee6b01000 0x000007fee6b023f0 Yes (*) C:\Windows\system32\api-ms-win-core-timezone-l1-1-0.dll 0x000007fee6af1000 0x000007fee6af23f0 Yes (*) C:\Windows\system32\api-ms-win-core-file-l2-1-0.dll 0x000007fee6ae1000 0x000007fee6ae23f0 Yes (*) C:\Windows\system32\api-ms-win-core-localization-l1-2-0.dll 0x000007fef05e1000 0x000007fef05e23f0 Yes (*) C:\Windows\system32\api-ms-win-core-synch-l1-2-0.dll 0x000007fee6ad1000 0x000007fee6ad23f0 Yes (*) C:\Windows\system32\api-ms-win-core-processthreads-l1-1-1.dll 0x000007fee6ac1000 0x000007fee6ac23f0 Yes (*) C:\Windows\system32\api-ms-win-core-file-l1-2-0.dll (*): Shared library is missing debugging information. (gdb) maint info breakpoints Num Type Disp Enb Address What -24 longjmp master keep n 0x0000000077800fa0 <ntdll!longjmp> inf 1 -24.1 y- 0x0000000077800fa0 <ntdll!longjmp> inf 1 -25 longjmp master keep n 0x000007feff6de540 <msvcrt!longjmp> inf 1 -25.1 y- 0x000007feff6de540 <msvcrt!longjmp> inf 1 -26 longjmp master keep n 0x000007fee6b431c0 <ucrtbase!longjmp> inf 1 -26.1 y- 0x000007fee6b431c0 <ucrtbase!longjmp> inf 1 (gdb) n warning: error removing breakpoint 0 at 0x7fee6b431c0 9 printf ("hi\n"); (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00000000777b1000 0x00000000779584e0 Yes (*) C:\Windows\SYSTEM32\ntdll.dll 0x0000000077691000 0x00000000777aeab8 Yes (*) C:\Windows\system32\kernel32.dll 0x000007fefd691000 0x000007fefd6fb13c Yes (*) C:\Windows\system32\KernelBase.dll 0x000007feff6d1000 0x000007feff76e4bc Yes (*) C:\Windows\system32\msvcrt.dll (*): Shared library is missing debugging information. (gdb) maint info breakpoints Num Type Disp Enb Address What -24 longjmp master keep n 0x0000000077800fa0 <ntdll!longjmp> inf 1 -24.1 y- 0x0000000077800fa0 <ntdll!longjmp> inf 1 -25 longjmp master keep n 0x000007feff6de540 <msvcrt!longjmp> inf 1 -25.1 y- 0x000007feff6de540 <msvcrt!longjmp> inf 1 -26 longjmp master keep n 0x000007fee6b431c0 inf 1 -26.1 y- 0x000007fee6b431c0 inf 1 (gdb) n Warning: Cannot insert breakpoint 0. Cannot access memory at address 0x7fee6b431c0 Command aborted. (gdb) maint info breakpoints Num Type Disp Enb Address What -24 longjmp master keep n 0x0000000077800fa0 <ntdll!longjmp> inf 1 -24.1 y- 0x0000000077800fa0 <ntdll!longjmp> inf 1 -25 longjmp master keep n 0x000007feff6de540 <msvcrt!longjmp> inf 1 -25.1 y- 0x000007feff6de540 <msvcrt!longjmp> inf 1 -26 longjmp master keep n 0x000007fee6b431c0 inf 1 -26.1 y- 0x000007fee6b431c0 inf 1 0 longjmp keep y 0x0000000077800fa0 <ntdll!longjmp> inf 1 stop only in thread 1 0.1 y 0x0000000077800fa0 <ntdll!longjmp> inf 1 0 longjmp keep y 0x000007feff6de540 <msvcrt!longjmp> inf 1 stop only in thread 1 0.1 y 0x000007feff6de540 <msvcrt!longjmp> inf 1 0 longjmp keep y 0x000007fee6b431c0 inf 1 stop only in thread 1 0.1 y 0x000007fee6b431c0 inf 1 ``` So there was an additional internal breakpoint set on ucrtbase!longjmp, but it wasn't removed when ucrtbase was unloaded. I do see multiple instances of libc after dlopen-ing libraries in a new linker namespace (CRTs, as you called them - only spelling it out for others that might be confused like me ;) It seems that GDB is trying to re-insert shlib event breakpoints into the libc from the second namespace that now no longer exists. We probably need GDB to recognize that that namespace is no longer valid... or we can try to be more generic, and in case we try to insert (certain types of?) internal breakpoints in a PC that has no object associated with it, we just delete the breakpoint instead. For extra debugging, this is the output of `info shared` and the internal breakpoints added by GDB: ``` (gdb) info shared From To Syms Read Shared Object Library 0x00007ffff7fc9000 0x00007ffff7ff09f5 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7ed2440 0x00007ffff7f49666 Yes (*) /lib64/libm.so.6 0x00007ffff7cf9800 0x00007ffff7e65cfd Yes (*) /lib64/libc.so.6 0x00007ffff7fbc040 0x00007ffff7fbc129 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib.1.so 0x00007ffff7fb7040 0x00007ffff7fb70f9 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib-dep.so 0x00007ffff7be0440 0x00007ffff7c57666 Yes (*) /lib64/libm.so.6 0x00007ffff7a07800 0x00007ffff7b73cfd Yes (*) /lib64/libc.so.6 0x00007ffff7fc9000 0x00007ffff7ff09f5 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7fa8040 0x00007ffff7fa8129 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib.1.so 0x00007ffff7cca040 0x00007ffff7cca0f9 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib-dep.so 0x00007ffff78f1440 0x00007ffff7968666 Yes (*) /lib64/libm.so.6 0x00007ffff7718800 0x00007ffff7884cfd Yes (*) /lib64/libc.so.6 0x00007ffff7fc9000 0x00007ffff7ff09f5 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7cc5040 0x00007ffff7cc5129 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib.2.so (*): Shared library is missing debugging information. (gdb) maint info breakpoints Num Type Disp Enb Address What -40 shlib events keep n 0x00007ffff7fe7edf <dl_main+6271> inf 1 -40.1 y- 0x00007ffff7fe7edf <dl_main+6271> inf 1 -41 shlib events keep y 0x00007ffff7fe83ba <dl_main+7514> inf 1 -41.1 y 0x00007ffff7fe83ba <dl_main+7514> inf 1 -42 shlib events keep n 0x00007ffff7fd04e5 <_dl_map_object_from_fd+4213> inf 1 -42.1 y- 0x00007ffff7fd04e5 <_dl_map_object_from_fd+4213> inf 1 -43 shlib events keep y 0x00007ffff7fd5177 <dl_open_worker_begin+1191> inf 1 -43.1 y 0x00007ffff7fd5177 <dl_open_worker_begin+1191> inf 1 -44 shlib events keep n 0x00007ffff7fc9f13 <_dl_close_worker+1859> inf 1 -44.1 y- 0x00007ffff7fc9f13 <_dl_close_worker+1859> inf 1 -45 shlib events keep y 0x00007ffff7fca1ca <_dl_close_worker+2554> inf 1 -45.1 y 0x00007ffff7fca1ca <_dl_close_worker+2554> inf 1 -70 longjmp master keep n 0x00007ffff7df79b9 <____longjmp_chk+249> inf 1 -70.1 y- 0x00007ffff7df79b9 <____longjmp_chk+249> inf 1 -71 longjmp master keep n 0x00007ffff7d11b57 <__longjmp_cancel+55> inf 1 -71.1 y- 0x00007ffff7d11b57 <__longjmp_cancel+55> inf 1 -72 longjmp master keep n 0x00007ffff7d11ad3 <__longjmp+163> inf 1 -72.1 y- 0x00007ffff7d11ad3 <__longjmp+163> inf 1 -73 longjmp master keep n 0x00007ffff7b059b9 <____longjmp_chk+249> inf 1 -73.1 y- 0x00007ffff7b059b9 <____longjmp_chk+249> inf 1 -74 longjmp master keep n 0x00007ffff7a1fb57 <__longjmp_cancel+55> inf 1 -74.1 y- 0x00007ffff7a1fb57 <__longjmp_cancel+55> inf 1 -75 longjmp master keep n 0x00007ffff7a1fad3 <__longjmp+163> inf 1 -75.1 y- 0x00007ffff7a1fad3 <__longjmp+163> inf 1 -76 longjmp master keep n 0x00007ffff78169b9 <____longjmp_chk+249> inf 1 -76.1 y- 0x00007ffff78169b9 <____longjmp_chk+249> inf 1 -77 longjmp master keep n 0x00007ffff7730b57 <__longjmp_cancel+55> inf 1 -77.1 y- 0x00007ffff7730b57 <__longjmp_cancel+55> inf 1 -78 longjmp master keep n 0x00007ffff7730ad3 <__longjmp+163> inf 1 -78.1 y- 0x00007ffff7730ad3 <__longjmp+163> inf 1 3 breakpoint keep y 0x000000000040130b /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../.. /binutils-gdb/gdb/testsuite/gdb.base/dlmopen.c:61 inf 1 breakpoint already hit 2 times 3.1 y 0x000000000040130b /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../.. /binutils-gdb/gdb/testsuite/gdb.base/dlmopen.c:61 inf 1 (gdb) n warning: error removing breakpoint 0 at 0x7ffff78169b9 warning: error removing breakpoint 0 at 0x7ffff7730b57 warning: error removing breakpoint 0 at 0x7ffff7730ad3 54 for (dl = 0; dl < 4; ++dl) ``` And the results after closing handle[2] (which closes the linker namespace) are: ``` (gdb) info shared From To Syms Read Shared Object Library 0x00007ffff7fc9000 0x00007ffff7ff09f5 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7ed2440 0x00007ffff7f49666 Yes (*) /lib64/libm.so.6 0x00007ffff7cf9800 0x00007ffff7e65cfd Yes (*) /lib64/libc.so.6 0x00007ffff7fbc040 0x00007ffff7fbc129 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib.1.so 0x00007ffff7fb7040 0x00007ffff7fb70f9 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib-dep.so 0x00007ffff7be0440 0x00007ffff7c57666 Yes (*) /lib64/libm.so.6 0x00007ffff7a07800 0x00007ffff7b73cfd Yes (*) /lib64/libc.so.6 0x00007ffff7fc9000 0x00007ffff7ff09f5 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7cc5040 0x00007ffff7cc5129 Yes /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs /gdb.base/dlmopen/dlmopen-lib.2.so (*): Shared library is missing debugging information. (gdb) maint info breakpoints Num Type Disp Enb Address What -40 shlib events keep n 0x00007ffff7fe7edf <dl_main+6271> inf 1 -40.1 y- 0x00007ffff7fe7edf <dl_main+6271> inf 1 -41 shlib events keep y 0x00007ffff7fe83ba <dl_main+7514> inf 1 -41.1 y 0x00007ffff7fe83ba <dl_main+7514> inf 1 -42 shlib events keep n 0x00007ffff7fd04e5 <_dl_map_object_from_fd+4213> inf 1 -42.1 y- 0x00007ffff7fd04e5 <_dl_map_object_from_fd+4213> inf 1 -43 shlib events keep y 0x00007ffff7fd5177 <dl_open_worker_begin+1191> inf 1 -43.1 y 0x00007ffff7fd5177 <dl_open_worker_begin+1191> inf 1 -44 shlib events keep n 0x00007ffff7fc9f13 <_dl_close_worker+1859> inf 1 -44.1 y- 0x00007ffff7fc9f13 <_dl_close_worker+1859> inf 1 -45 shlib events keep y 0x00007ffff7fca1ca <_dl_close_worker+2554> inf 1 -45.1 y 0x00007ffff7fca1ca <_dl_close_worker+2554> inf 1 -70 longjmp master keep n 0x00007ffff7df79b9 <____longjmp_chk+249> inf 1 -70.1 y- 0x00007ffff7df79b9 <____longjmp_chk+249> inf 1 -71 longjmp master keep n 0x00007ffff7d11b57 <__longjmp_cancel+55> inf 1 -71.1 y- 0x00007ffff7d11b57 <__longjmp_cancel+55> inf 1 -72 longjmp master keep n 0x00007ffff7d11ad3 <__longjmp+163> inf 1 -72.1 y- 0x00007ffff7d11ad3 <__longjmp+163> inf 1 -73 longjmp master keep n 0x00007ffff7b059b9 <____longjmp_chk+249> inf 1 -73.1 y- 0x00007ffff7b059b9 <____longjmp_chk+249> inf 1 -74 longjmp master keep n 0x00007ffff7a1fb57 <__longjmp_cancel+55> inf 1 -74.1 y- 0x00007ffff7a1fb57 <__longjmp_cancel+55> inf 1 -75 longjmp master keep n 0x00007ffff7a1fad3 <__longjmp+163> inf 1 -75.1 y- 0x00007ffff7a1fad3 <__longjmp+163> inf 1 -76 longjmp master keep n 0x00007ffff78169b9 inf 1 -76.1 y- 0x00007ffff78169b9 inf 1 -77 longjmp master keep n 0x00007ffff7730b57 inf 1 -77.1 y- 0x00007ffff7730b57 inf 1 -78 longjmp master keep n 0x00007ffff7730ad3 inf 1 -78.1 y- 0x00007ffff7730ad3 inf 1 3 breakpoint keep y 0x000000000040130b /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../.. /binutils-gdb/gdb/testsuite/gdb.base/dlmopen.c:61 inf 1 breakpoint already hit 3 times 3.1 y 0x000000000040130b /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../.. /binutils-gdb/gdb/testsuite/gdb.base/dlmopen.c:61 inf 1 ``` I came up with this: ``` --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -8049,6 +8049,7 @@ static void disable_breakpoints_in_unloaded_shlib (program_space *pspace, const solib &solib) { bool disabled_shlib_breaks = false; + bool remove_disabled_longjmp_breaks = false; for (bp_location *loc : all_bp_locations ()) { @@ -8059,6 +8060,8 @@ disable_breakpoints_in_unloaded_shlib (program_space *pspace, const solib &solib && !loc->shlib_disabled && (((b->type == bp_breakpoint || b->type == bp_jit_event + || b->type == bp_longjmp + || b->type == bp_longjmp_master || b->type == bp_hardware_breakpoint) && (loc->loc_type == bp_loc_hardware_breakpoint || loc->loc_type == bp_loc_software_breakpoint)) @@ -8071,6 +8074,13 @@ disable_breakpoints_in_unloaded_shlib (program_space *pspace, const solib &solib to prevent future errors occurring in remove_breakpoints. */ loc->inserted = 0; + if (b->type == bp_longjmp + || b->type == bp_longjmp_master) + { + remove_disabled_longjmp_breaks = true; + continue; + } + /* This may cause duplicate notifications for the same breakpoint. */ notify_breakpoint_modified (b); @@ -8084,6 +8094,12 @@ disable_breakpoints_in_unloaded_shlib (program_space *pspace, const solib &solib disabled_shlib_breaks = true; } } + + if (remove_disabled_longjmp_breaks) + for (breakpoint &b : all_breakpoints_safe ()) + if ((b.type == bp_longjmp || b.type == bp_longjmp_master) + && b.first_loc ().shlib_disabled) + delete_breakpoint (&b); } /* Disable any breakpoints and tracepoints in OBJFILE upon ``` I'm not completely sure if it's the correct approach to fix this, but it works for Windows at least. If this happens with longjmp breakpoints, it can probably happen with the C++ exception breakpoints as well. I've posted a proposed fix for this bug here: https://inbox.sourceware.org/gdb-patches/cover.1724948606.git.aburgess@redhat.com/ It is inspired by the changes Hannes Domani proposed in: https://sourceware.org/bugzilla/show_bug.cgi?id=32079#c3 But when combined with an earlier patch in the series I don't think the delete_breakpoint call is needed. And as Tom pointed out I handle more b/p types as well as fixing another issue that cropped up during testing. |