einpoklum
einpoklum

Reputation: 132138

Can I suppress a specific linker warning about a specific location?

My project code links against some libraries whose source I don't have. During linking I get:

/usr/x86_64-suse-linux/bin/ld:libfoo.a(foo.o): in function `flush':
source/readcfg.c:1234:(.text+0xabc): warning: the use of `tmpnam' is dangerous, better use `mkstemp'
/usr/x86_64-suse-linux/bin/libbar.a(.o): in function `getErmes':
source/bar.c:123:(.text+0x1238): warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead

Can I suppress these messages (or these kinds of messages), without having edited the source files for foo and bar?

(Note: for compiler errors, we can set -Wsomething and -Wno-something to enable or suppress. This is even true for some GNU ld warnings, as its man ld describes several --warn/--nowarn options.)

Related: warning: the use of `tmpnam' is dangerous, better use `mkstemp' discusses how to avoid the error from the get-go.

Upvotes: 1

Views: 116

Answers (1)

Quuxplusone
Quuxplusone

Reputation: 27324

These diagnostics come from special .gnu.warning sections in the standard library's .o files. (Thanks to this question for giving the hint.) That is, "tmpnam.o" contains a special section named .gnu.warning.tmpnam. When GNU ld sees that section (and a use of tmpnam), it prints the warning.

According to fcambus/gwcheck, the .gnu.warning logic is implemented in GNU ld and gold, but not in LLVM lld nor on Solaris.

Someone in the 2006 OSDev thread suggests that you could do something "clever" involving objcopy --remove-section: basically "preprocess" libc.a or libc.so for use with your project, then link against the preprocessed/stripped libc.

Similarly, objcopy --rename-section.


A partial solution might involve gcc -Wl,--wrap,tmpnam *.o. This causes ld to treat every unresolved reference to tmpnam as if it were an unresolved reference to __wrap_tmpnam instead. But then you still have to write your own implementation of __wrap_tmpnam — and you can't implement it by just calling __real_tmpnam, because that'll trigger the warning again.

Of course if you're willing to reimplement tmpnam, then you could just add your own tmpnam.o to your project; you don't need to involve --wrap.


The simplest solution might actually be "use an alternative to GNU ld," such as mold or lld. (But not GNU gold, which has the same behavior as ld.)

Or, set your CC/CXX environment variable to point not to /usr/bin/gcc but to a simple shell script like (thanks to this question for explaining how to filter stderr only):

cat >gcc.sh <<EOF
#!/bin/bash
gcc "$@" 2> >(sed -n -e "/tmpnam' is dangerous/{s/.*//;x;d};x;p" >&2)
EOF
CC=./gcc.sh

(Sorry, my sed-fu is bad. The intent here is to eliminate the line containing tmpnam' is dangerous and also the immediately preceding line.)


One thing that does not work (as of 2024) is to just add your own empty warning message for tmpnam, like this:

cat >dummy.c <<EOF
static const char msg[0] __attribute__((section(".gnu.warning.tmpnam")));
EOF
cat >main.c <<EOF
#include <stdio.h>
int main() { char s[100]; tmpnam(s); }
EOF
gcc -c main.c dummy.c

This does "override" the message from libc.so, but it doesn't cause the warning to disappear — it just causes the warning message to become empty, like this:

$ gcc dummy.o main.o
/usr/bin/ld: main.o: in function `main':
main.c:(.text+0x10): warning: 

It certainly seems like (as of 2024) there is no simple or one-line solution to this problem.

Upvotes: 1

Related Questions