The following gdb test cases fail similarly on PowerPC. gdb.base/annota1.exp gdb.base/annota3.exp gdb.server/sysroot.exp Lets take annota1.exp as an example. I run the test with the command: make check RUNTESTFLAGS='GDB=/home/carll/bin/gdb gdb.base/annota1.exp ' The log file contents: ... PASS: gdb.base/annota1.exp: break printf continue post-prompt Continuing. starting frames-invalid value is 7 my_array[2] is 3 exited 0 [Inferior 1 (process 1853544) exited normally] thread-exited,id="1",group-id="i1" stopped pre-prompt (gdb) prompt FAIL: gdb.base/annota1.exp: continue to printf ... ---------------------- I think it is a little more informative to actually run the test by hand. I cd to the location of the test binary: gdb/testsuite/outputs/gdb.base/annota1 gdb ./annota1 (gdb) break main Breakpoint 1 at 0x100007b8: file .../binutils-gdb-printf/gdb/testsuite/gdb.base/annota1.c, line 15. (gdb) run Starting program: ...build-printf/gdb/testsuite/outputs/gdb.base/annota1/annota1 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1, main () at .../binutils-gdb-printf/gdb/testsuite/gdb.base/annota1.c:15 15 int my_array[3] = { 1, 2, 3 }; /* break main */ (gdb) break printf Downloading source file /usr/src/debug/glibc-2.35-17.fc36.ppc64le/stdio-common/printf.c... Breakpoint 2 at 0x7ffff7a7cb58: file printf.c, line 28. (gdb) list 20 signal (SIGUSR1, handle_USR1); 21 #endif 22 23 printf ("value is %d\n", value); 24 printf ("my_array[2] is %d\n", my_array[2]); (gdb) break 23 Breakpoint 3 at 0x100007f4: file .../binutils-gdb-printf/gdb/testsuite/gdb.base/annota1.c, line 23. (gdb) c Continuing. Breakpoint 3, main () at .../binutils-gdb-printf/gdb/testsuite/gdb.base/annota1.c:23 23 printf ("value is %d\n", value); (gdb) c Continuing. value is 7 my_array[2] is 3 [Inferior 1 (process 1854022) exited normally] So we can see that it didnt' stop at the printf call. Rerun but this time stop at line 23 and then do a step. Breakpoint 3, main () at .../binutils-gdb-printf/gdb/testsuite/gdb.base/annota1.c:23 23 printf ("value is %d\n", value); (gdb) step 0x00007ffff7a94a48 in ___ieee128_printf (format=0x10000920 "value is %d\n") at ../sysdeps/ieee754/ldbl-128ibm-compat/ieee128-printf.c:24 24 { We can see that execution stopped in file ieee128-printf.c but gdb set the breakpoint in file printf.c, line 28. Per a suggestion that I was given that the issue maybe with the DWARF, I dumped the dwarf for annota1. objd readelf --debug-dump annota1 > annota1.dwarf The file has the following intersting info: <af> DW_AT_external : 1 <af> DW_AT_location : 9 byte block: 3 38 0 2 10 0 0 0 0 (DW_OP_addr: 10020038) <1><b9>: Abbrev Number: 10 (DW_TAG_subprogram) <ba> DW_AT_external : 1 <ba> DW_AT_name : (indirect string, offset: 0xd5): printf <be> DW_AT_decl_file : 2 <bf> DW_AT_decl_line : 24 <c0> DW_AT_decl_column : 1 <c1> DW_AT_linkage_name: (indirect string, offset: 0xe2): __printfieee128 <c5> DW_AT_prototyped : 1 <c5> DW_AT_type : <0x64> The thought is that gdb should be using the DW_AT_linkage_name to find the correct function to set the break point. I have put print statements into gdb/dwarf2/read.c at the various locations where DW_AT_linkage_name exists to see if I see gdb process the DWARF entry for the __printfieee128. Specifically: case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: /* Note that both forms of linkage name might appear. We assume they will be the same, and we only store the last one we see. */ if (*linkage_name == nullptr) *linkage_name = attr.as_string (); printf("CARLL, scan attributes, case DW_AT_linkage_name %s\n", *linkage_name); break; in cooked_indexer::scan_attributes. I have been poking around but so far, I have not been able to find any evidence that the dwarf for annota1 gets read, specifically gdb processes the DW_AT_linkage_name for __printfieee128. Not sure if I am off in the weeds trying to figure out what the issue is or not.
I was given a suggestion of trying rbreak printf. When I run this command I get asked Make breakpoint pending on future shared library load? (y or [n]) after answering the question a buzillion times you eventually get back to the gdb prompt. <function, no debug info> 00000020.plt_call._dl_fatal_printf@@GLIBC_PRIVATE; Breakpoint 1062 at 0x7ffff7bdb9b4 <function, no debug info> _dl_fatal_printf@plt; (gdb) (gdb) (gdb) c Continuing. Breakpoint 157, 0x00000000100005a0 in 0000001b.plt_call.__printfieee128@@GLIBC_2.32 () not sure exactly where we are but if we do a few step commands we then see (gdb) s Single stepping until exit from function __printfieee128@plt, which has no line number information. (gdb) s Single stepping until exit from function __glink_PLTresolve, which has no line number information. ___ieee128_printf (format=0x10000920 "value is %d\n") at ../sysdeps/ieee754/ldbl-128ibm-compat/ieee128-printf.c:24 24 { (gdb) list 19 #include <stdarg.h> 20 #include <libio/libioP.h> 21 22 extern int 23 ___ieee128_printf (const char *format, ...) 24 { 25 va_list ap; 26 int done; 27 28 va_start (ap, format); not sure what all this means yet but thought is was interesting.
The issue occurs with the Fedora 38 release. The issue does not occur with Ubuntu 22.04.
This issue occurs with Fedora 38. The issue does not occur with Ubuntu 22.04.
Digging into the issue further, the issue is not limited to the printf function but all of the symbols for the IEEE 128-bit floating point functions that are redirected in glibc. PowerPC supports the IBM 128-bit floating point format and the IEEE 128-bit floating point format. The IEEE 128 bit support redirects the various function calls to the ieee128 versions of the functions. For example, the printf function gets linked to the __printfieee128 function at linking time. Gdb is not aware of the __printfieee128 symbol was redirected from the original printf symbol so it only sets a breakpoint in the standard printf function. GDB fails to break in the redirected printf function. The printf function is just one of about 200 IEEE128 bit functions that get remapped for PowerPC. Ulrich and I have looked at fixing this in gdb by creating hidden symbols for printf that points to the __printfieee128 function. Although it is possible to do, in general it is really messy/hard to do because because of the naming scheme that was used. The original function was mapped to an ieee128 bit function with one of the following mappings: foo -> __fooieee128 fool -> __fooieee128 foo -> __newnameieee128 foo_r -> __fooieee128_r In GDB, you have to do the reverse mapping from to determine what the original function name "foo" so you can create a hidden symbol for "foo" that points to the IEEE 128 bit symbol "__fooiiieee128". We have tried to come up with a simple reverse mapping algorithm, but since __fooieee128 can map back to either foo or fool you have to search the entire list of mappings to determine what the original name was. Note, there are also some existing symbol names with ieee128 in them that are not the result of redirecting function foo to its IEEE 128 equivalent function. These also cannot be eliminated without going thru the list of known symbol names that have been redirected. A proof of concept patch in gdb which takes the symbol and searches the list of 200+ redirected function names to determine the original symbol name was done and works. The issue is maintaining the list of 200+ function mappings in gdb is fragile and not considered an acceptable solution. The feeling is the right thing to do is to have glibc emit a local symbol in the library binary, i.e. printf that points to the redirected symbol, i.e. __printfieee128. When the user types "break printf" GDB will set a breakpoint in the original printf function and in the __printfieee128 function via the local printf symbol in the glibc library. Basically, have glibc create the hidden symbol for each of the 200 or so redirected functions rather than having gdb create the hidden symbol as was done in the proof of concept patch. The advantage of having glibc add the local symbol to the library binary is it already knows what symbols are being redirected and gdb doesn't have to maintain a list of mappings. The new redirected symbols need to be dynamic symbols in case only the stripped binary is available.