Bug 88643 - -Wl,--wrap not supported with LTO
Summary: -Wl,--wrap not supported with LTO
Status: RESOLVED MOVED
Alias: None
Product: gcc
Classification: Unclassified
Component: lto (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: lto
: 89930 115953 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-12-31 12:19 UTC by Martin Liška
Modified: 2024-07-16 19:39 UTC (History)
10 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-01-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Liška 2018-12-31 12:19:49 UTC
Seen in cmocka package:

$ cat foo.h
int cook(void);

$ cat foo.c
#include "foo.h"

int __wrap_cook(void)
{
  return 0;
}

$ cat bar.c
int cook(void)
{
  return -1;
}

$ cat main.c
#include "foo.h"

int main()
{
  if (cook () == -1)
    __builtin_abort ();

  return 0;
}

$ gcc main.c foo.c bar.c -Wl,--wrap=cook && ./a.out
(ok)

$ gcc main.c foo.c bar.c -Wl,--wrap=cook -flto && ./a.out 
Aborted (core dumped)

$ cat main.res
3
main.o 2
198 afba4c81ec45b173 PREVAILING_DEF main
215 afba4c81ec45b173 RESOLVED_IR cook
foo.o 1
197 34da4dbae42a1068 PREVAILING_DEF_IRONLY __wrap_cook
bar.o 1
197 d2fb0e1d62586272 PREVAILING_DEF_IRONLY cook

I'm not sure there's an API for linker plugin to resolve a symbol with a deferent one. Honza?
Comment 1 Richard Biener 2019-01-02 11:45:05 UTC
There isn't support for this kind of replacement.  I guess the resolution
output could be enhanced to handle this.
Comment 2 Sebastian Huber 2019-01-17 07:23:20 UTC
Is this somehow related to the problem that the LD --wrap does not work for references internal to a translation unit? See:

https://www.sourceware.org/ml/binutils/2018-12/msg00210.html

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=4ea904edb7b04ad526bd8a5401729a6c1f5a982f
Comment 3 Sergei Trofimovich 2019-01-24 22:47:19 UTC
One of Gentoo users rediscovered similar bug on cmocka-1.1.3 project:
    https://bugs.gentoo.org/675876

It exhibits as a linker failure:

# LANG=C make V=1 VERBOSE=1
/usr/lib64/ccache/bin/x86_64-pc-linux-gnu-gcc -O2 -pipe -flto -fdiagnostics-show-option -frecord-gcc-switches  -Wl,-O1 -Wl,--as-needed -O2 -pipe -flto -Wl,--hash-style=gnu  -Wl,--wrap=uptime CMakeFiles/test_uptime.dir/test_uptime.c.o  -o test_uptime -Wl,-rpath,/dev/shm/portage/dev-util/cmocka-1.1.3/work/cmocka-1.1.3-abi_x86_64.amd64/src ../../../src/libcmocka.so.0.5.1 /usr/lib/librt.so 
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: /tmp/cc3ig6Xu.ltrans0.ltrans.o: in function `calc_uptime':
<artificial>:(.text+0x46): undefined reference to `__wrap_uptime'
collect2: error: ld returned 1 exit status

Would extracting another example be useful here?
Comment 4 Martin Liška 2019-01-25 09:41:56 UTC
> 
> Would extracting another example be useful here?

No, but thank you for the report.
Note that bintuils has recently documented that:

commit 6406a2701bda7437e879bff026adc8a5a94e87ff (HEAD, origin/master, origin/HEAD)
Author: Sebastian Huber <sebastian.huber@embedded-brains.de>
Date:   Mon Jan 14 08:30:19 2019 +0100

    ld: Add LTO warning to --wrap documentation
    
    ld/
    
            * ld.texi (--wrap): Add warning that LTO may make this feature
            ineffective.
Comment 5 Sebastian Huber 2019-01-25 09:48:20 UTC
I think the basic problem is that the LD --wrap feature works only with undefined symbols references and not relocations:

See also:

https://www.sourceware.org/ml/binutils/2019-01/msg00204.html
Comment 6 Andrew Pinski 2019-04-02 17:13:14 UTC
*** Bug 89930 has been marked as a duplicate of this bug. ***
Comment 7 Дилян Палаузов 2019-04-02 18:27:58 UTC
As noted at https://sourceware.org/bugzilla/show_bug.cgi?id=24406 this does work with clang+gold and clang+lld, but not with clang+bfd.

As this does not work with gcc+gold, the problem is not in the linker.
Comment 8 H.J. Lu 2019-04-03 13:31:44 UTC
A linker patch is posted at

https://sourceware.org/ml/binutils/2019-04/msg00018.html

But it won't work with -O2 since LTO inlines cook before linker can wrap
it.
Comment 9 Дилян Палаузов 2019-04-03 14:18:25 UTC
With the patch applied to ld.bfd “clang -flto -fuse-ld=bfd -Wl,--wrap=read t.c” does work.
Comment 10 Дилян Палаузов 2019-04-03 14:26:20 UTC
With the patch applied this works:

clang -flto -fuse-ld=bfd  -Wl,--wrap=read -O3 t.c
gcc   -flto -fuse-ld=bfd  -Wl,--wrap=read -O3 t.c
gcc   -flto -fuse-ld=bfd  -Wl,--wrap=read -O2 t.c
gcc   -flto -fuse-ld=bfd  -Wl,--wrap=read -O1 t.c

This does not work:

gcc   -flto -fuse-ld=gold -Wl,--wrap=read -O3 t.c
gcc   -flto -fuse-ld=gold -Wl,--wrap=read -O2 t.c
gcc   -flto -fuse-ld=gold -Wl,--wrap=read -O1 t.c
Comment 11 Дилян Палаузов 2019-04-03 14:34:52 UTC
Reported for ld.gold at https://sourceware.org/bugzilla/show_bug.cgi?id=24415 .
Comment 12 Andrew Pinski 2022-01-01 12:09:16 UTC
Since GCC does work but not with gold, the bug is in gold. I am going to close this as moved. https://sourceware.org/bugzilla/show_bug.cgi?id=24415 records the binutils/gold bug.
Comment 13 Richard Biener 2024-07-16 10:50:02 UTC
*** Bug 115953 has been marked as a duplicate of this bug. ***
Comment 14 Richard Biener 2024-07-16 11:00:00 UTC
Just to note with BFD ld from 2.41.0 I see

1
a-t.o 3
194 b4b00c6ef6ad050b PREVAILING_DEF_IRONLY __wrap_cook
198 b4b00c6ef6ad050b PREVAILING_DEF main
214 b4b00c6ef6ad050b RESOLVED_IR cook

when building

int cook(void);
int __wrap_cook(void)
{
  return 0;
}
int main()
{
  if (cook () == -1)
    __builtin_abort ();

  return 0;
}

but an LTO link fails with

/usr/lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/bin/ld: ./a.ltrans0.ltrans.o: in function `main':
<artificial>:(.text+0x10): undefined reference to `__wrap_cook'

GCC emits at LTRANS stage

        .file   "<artificial>"
        .text
        .type   __wrap_cook, @function
__wrap_cook:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   __wrap_cook, .-__wrap_cook
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        call    cook
        cmpl    $-1, %eax
        jne     .L4
        call    abort
.L4:
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret

which I think should be OK.  The main difference is that __wrap_cook is
an internal symbol but that's OK since the linker told GCC

194 b4b00c6ef6ad050b PREVAILING_DEF_IRONLY __wrap_cook

it probably should have used

194 b4b00c6ef6ad050b PREVAILING_DEF __wrap_cook

instead.
Comment 15 Sam James 2024-07-16 19:39:03 UTC
H.J. has fixed this for upcoming binutils-2.43.