Created attachment 15437 [details] C program for demonstrating problems w/ errno I am writing a new gdb test, gdb.base/check-errno.exp. (Actually, it's a rewrite of an old test written by Jan Kratochvil from a while back, perhaps as far back as 2008.) The test compiles a simple program multiple times, each time using different compile flags. In some cases, GDB is able to print errno correctly and in other cases it does not. The program is named check-errno.c. Here are the instances where GDB is unable to access errno: 1) -static: kev@f39-1:ce$ gcc -static -g -o check-errno-static check-errno.c kev@f39-1:ce$ $GDB -q check-errno-static Reading symbols from check-errno-static... (gdb) b 24 Breakpoint 1 at 0x401794: file check-errno.c, line 24. (gdb) run Starting program: /tmp/ce/check-errno-static This GDB supports auto-downloading debuginfo from the following URLs: <https://debuginfod.fedoraproject.org/> Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. Downloading separate debug info for system-supplied DSO at 0x7ffff7ffd000 Breakpoint 1, main () at check-errno.c:24 24 return 0; /* breakpoint */ (gdb) p errno Cannot find thread-local storage for process 14409, executable file /tmp/ce/check-errno-static: Cannot find thread-local variables on this target 2) -static -g3: kev@f39-1:ce$ gcc -static -g3 -o check-errno-static check-errno.c kev@f39-1:ce$ $GDB -q check-errno-static Reading symbols from check-errno-static... (gdb) b 24 Breakpoint 1 at 0x401794: file check-errno.c, line 24. (gdb) run Starting program: /tmp/ce/check-errno-static This GDB supports auto-downloading debuginfo from the following URLs: <https://debuginfod.fedoraproject.org/> Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. Breakpoint 1, main () at check-errno.c:24 24 return 0; /* breakpoint */ (gdb) p errno '__errno_location' has unknown return type; cast the call to its declared return type 3, 4) Same as above, but use gcore to make a core file for above two cases. 5) -lpthread -g3, from corefile: kev@f39-1:ce$ gcc -lpthreads -g3 -o check-errno-pthreads-g3 check-errno.c /usr/bin/ld: cannot find -lpthreads: No such file or directory collect2: error: ld returned 1 exit status kev@f39-1:ce1$ gcc -lpthread -g3 -o check-errno-pthreads-g3 check-errno.c kev@f39-1:ce$ $GDB -q check-errno-pthreads-g3 Reading symbols from check-errno-pthreads-g3... (gdb) b 24 Breakpoint 1 at 0x401135: file check-errno.c, line 24. (gdb) run Starting program: /tmp/ce/check-errno-pthreads-g3 This GDB supports auto-downloading debuginfo from the following URLs: <https://debuginfod.fedoraproject.org/> Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1, main () at check-errno.c:24 24 return 0; /* breakpoint */ (gdb) p errno $1 = 42 (gdb) gcore check-errno-pthreads-gc.core warning: Memory read failed for corefile section, 4096 bytes at 0xffffffffff600000. Saved corefile check-errno-pthreads-gc.core (gdb) core check-errno-pthreads-gc.core A program is being debugged already. Kill it? (y or n) y [New LWP 14550] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Core was generated by `/tmp/ce/check-errno-pthreads-g3'. Program terminated with signal SIGTRAP, Trace/breakpoint trap. #0 main () at check-errno.c:24 24 return 0; /* breakpoint */ (gdb) p errno You can't do that without a process to debug. The above behavior was observed on Fedora 39, which is using the following version of gcc: gcc (GCC) 13.2.1 20240316 (Red Hat 13.2.1-7) Fedora GDB has a hack which causes errno to be printed correctly for each of these cases. However, IMO, it truly is a hack and is not acceptable for upstream. I would like to figure out and fix (if possible) the root cause of each of the problems above so that the hack may be discarded.
I plan to look into these various errno problems...
FWIW, this: ... diff --git a/gdb/infcall.c b/gdb/infcall.c index 23d5652dd21..bf836c93152 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -1092,9 +1092,13 @@ call_function_by_hand_dummy (struct value *function, { const char *name = get_function_name (funaddr, name_buf, sizeof (name_buf)); - error (_("'%s' has unknown return type; " - "cast the call to its declared return type"), - name); + if (gdbarch_osabi (gdbarch) == GDB_OSABI_LINUX + && strcmp (name, "__errno_location") == 0) + values_type = lookup_pointer_type (builtin_type (gdbarch)->builtin_int); + else + error (_("'%s' has unknown return type; " + "cast the call to its declared return type"), + name); } values_type = check_typedef (values_type); ... gives a few xpasses on the new test-case: ... XPASS: gdb.base/check-errno.exp: macros: print errno XPASS: gdb.base/check-errno.exp: macros: print (int) errno XPASS: gdb.base/check-errno.exp: pthreads-macros: print errno XPASS: gdb.base/check-errno.exp: pthreads-macros: print (int) errno ... But it's still a bit hacky, in the sense that it doesn't fix ptype __errno_location, in other words, it only has effect when doing an inferior call.
The macro case should be fixed by adding the cast to the macro itself, IMNSHO. I.e., with a patch to glibc's errno header to insert the explicit cast there.
Regarding the type of __errno_location... When I run the test, compiled with -g3, on a machine without installed glibc debuginfo and also with debuginfod disabled, I see: (gdb) p errno '__errno_location' has unknown return type; cast the call to its declared return type But, when I look at the DWARF for the binary, I see: <1><32>: Abbrev Number: 2 (DW_TAG_subprogram) <33> DW_AT_external : 1 <33> DW_AT_name : (indirect string, offset: 0x1f7e): __errno_location <37> DW_AT_decl_file : 2 <38> DW_AT_decl_line : 37 <39> DW_AT_decl_column : 13 <3a> DW_AT_prototyped : 1 <3a> DW_AT_type : <0x3e> <3e> DW_AT_declaration : 1 <1><3e>: Abbrev Number: 3 (DW_TAG_pointer_type) <3f> DW_AT_byte_size : 8 <40> DW_AT_type : <0x44> <1><44>: Abbrev Number: 4 (DW_TAG_base_type) <45> DW_AT_byte_size : 4 <46> DW_AT_encoding : 5 (signed) <47> DW_AT_name : int So gdb could know the type if it didn't ignore it. (It is ignored in read_func_scope in gdb/dwarf2/read.c due to not having low and high pc attributes.)
Indeed. It has no pc range because it's a declaration (DW_AT_declaration). It would also be interesting to test accessing errno in a program that never references it. Like: int main() { return 0; // stop here and access errno. } This models a program that actually calls some function that sets errno, but in a different translation unit, potentially even in a library, and then the user wants to inspect errno. Does your testcase cover this scenario? This reminded me of clang's -fstandalone-debug, which is on by default: https://clang.llvm.org/docs/UsersManual.html#cmdoption-fstandalone-debug which I guess could also affect some of these scenarios.
(In reply to Pedro Alves from comment #5) > It would also be interesting to test accessing errno in a program that never > references it. Like: > > int main() > { > return 0; // stop here and access errno. > } > > This models a program that actually calls some function that sets errno, but > in a different translation unit, potentially even in a library, and then the > user wants to inspect errno. > > Does your testcase cover this scenario? No. I'd be inclined to write another/different test for that scenario. Also, I think that such a test should make a library/system call since the above example need not provide access to errno.