Please explain an odd glibc behavior

On Fedora 33 Workstation if I try to put a break point on printf()
before the program is executed, I’m informed the function does not exist
by gdb. If I break on main(), I’m allowed put a break on printf() that’s never reached when execution is continued. If I break on main() and
step into printf() I reach _IO_puts().

#include "stdio.h"
void main() {
printf("Hello Void!");
}

Sorry, the textual summary at the moment isn’t quite clear enough for someone to try and reproduce your issue to investigate it.

Can you please give step by step summaries of what you did, what you got, and what you expect to get?

Of course, the relevant package versions are needed too: gcc, glibc, etc.

Are you using the name of the function “printf” as your breakpoint, or the line that printf is on?
One will drop you inside of printf, which is a glibc function, and will require that you install the packages containing the debug symbols in order to actually get any useful information beyond the assembly code, and the other will stop you at the line that your printf is on.

If all you’re trying to do, is step to the line, you could also use “start” and then “next”/“step”. You can also use “break” when doing this, to add a break at a specific line for the next run.

If you try to place a breakpoint before starting the program, you haven’t entered the scope of main(), so gdb will have no context for printf(), as it’s, again, a glibc function, and not a part of your program.

1 Like

Thanx!
The significant installed packages are:

glibc-2.32-4.fc33.x86_64
glibc-debuginfo-2.32-4.fc33.x86_64

$ ldd hello
linux-vdso.so.1 (0x00007ffedede4000)
libc.so.6 => /lib64/libc.so.6 (0x00007f624e395000)
/lib64/ld-linux-x86-64.so.2 (0x00007f624e59a000)

hello.c:
#include “stdio.h”

void main() {
printf(“Hello Void!\n”);
}

Makefile:
hello: hello.c
gcc -g --save-temps -o hello hello.c

ddd hello

(gdb) break main
Breakpoint 1 at 0x40112a: file hello.c, line 4.
(gdb) break printf
Function “printf” not defined.
(gdb)
If I step through the code starting at the break on main() I reach:
int
_IO_puts (const char *str)
{
int result = EOF;
size_t len = strlen (str);
_IO_acquire_lock (stdout);

if ((_IO_vtable_offset (stdout) != 0
|| _IO_fwide (stdout, -1) == -1)
&& _IO_sputn (stdout, str, len) == len
&& _IO_putc_unlocked (‘\n’, stdout) != EOF)
result = MIN (INT_MAX, len + 1);

_IO_release_lock (stdout);
return result;
}

weak_alias (_IO_puts, puts)
libc_hidden_def (_IO_puts)

I just got the same result on Fedora 34 Workstation Beta after installing the needed packages
in a toolbox environment.

And, over here on another installation of the same beta I got this that I thought was the
correct response to break printf

Bur, I think I’ve mangled the packages up.

That’s the correct behavior in gdb. “break <function>” is “break on entry of <function>”. This breaks at the first line of the function, any time it’s called.

There seems some compiler optimization foolery is going on. It looks almost like, on the first installs, printf() was compiled in as puts(), as it’s often faster, and you weren’t using any of the special formatting that printf() would be needed for. So, your source says printf(), but the binary is linked to puts() (IO_puts()).
Try explicitly using “-O0” or “-Og” when you’re compiling.

Big Thanks! Both -Og and using printf(“%i : %s\n”, 1, “Hello Void!”);
yielded expected results.