11

The man page of gcc 6.3 says:

--wrap=symbol
           Use a wrapper function for symbol.  Any undefined reference to
           symbol will be resolved to "__wrap_symbol".  Any undefined
           reference to "__real_symbol" will be resolved to symbol.
           ...
           If you link other code with this file using --wrap malloc, then all
           calls to "malloc" will call the function "__wrap_malloc" instead.
           The call to "__real_malloc" in "__wrap_malloc" will call the real
           "malloc" function.

So I created a simple example:

#include <stdio.h>

int foo() {
    printf("foo\n");
    return 0;
}

int __wrap_foo() {
    printf("wrap foo\n");
    return 0;
}

int main () {
    printf("foo:");foo();
    printf("wrapfoo:");__wrap_foo();
    printf("realfoo:");__real_foo();
    return 0;
}

And compiled it with:

gcc main.c -Wl,--wrap=foo -o main

This gave me a warning:

main.c:18:21: warning: implicit declaration of function ‘__real_foo’ [-Wimplicit-function-declaration]
  printf("realfoo:");__real_foo();
                     ^~~~~~~~~~

Well going on. Now I would suggest an output like this:

foo:wrap foo
wrapfoo:wrap foo
realfoo:foo

Instead I get this:

foo:foo
wrapfoo:wrap foo
realfoo:foo

I hope the thing is clear. I am confused about the warning. Normally the __real function should be linked by the linker to foo(). Furthermore a call to foo() should be linked to __wrap_foo. But the output showes, that foo() is being executed instead.

How to use --wrap correctly?

eDeviser
  • 1,605
  • 2
  • 17
  • 44
  • 5
    It did work. But because you have a single translation unit, and `foo` is present, the call to `foo` is not an **undefined reference** to `foo`. – StoryTeller - Unslander Monica Sep 27 '17 at 09:24
  • Well, I do not understand. The output of the example above seems wrong to me. `foo()` should output `"wrap foo"`! What am I doing wrong? – eDeviser Sep 27 '17 at 11:08
  • 2
    You are ignoring the "undefined reference" **requirement**. – StoryTeller - Unslander Monica Sep 27 '17 at 11:09
  • Wohooo, that's it! ...going now to compose a complete answer... – eDeviser Sep 27 '17 at 11:15
  • 5
    personal opinion: The correct way to use the `--wrap` stuff is not at all. It is a horrible workaround for when you just must link with certain libraries where you don't have the source and you have to do terrible things like this to make it work. It's a last ditch effort to save your sanity when you're out of all other options (including talking to the library vendor, then talking to your boss and threatening to quit if you have to keep using a bad library that requires hacks like this). – Art Sep 27 '17 at 11:28
  • That's all right with me. I'm using `--wrap` just to create some stubs and mock objects when there is no other choice to implementing some unit tests. – eDeviser Sep 27 '17 at 11:32

1 Answers1

19

As StoryTeller told me, I ignored the "undefined reference" requirement which I already posted above:

... Any undefined reference to symbol will be resolved to "__wrap_symbol". Any undefined reference to "__real_symbol" will be resolved to symbol.

To use the --wrap option I rearranged my code example like this:

main.c:

#include <stdio.h>
extern int foo();
extern int __real_foo();

int __wrap_foo() {
    printf("wrap foo\n");
    return 0;
}

int main () {
    printf("foo:");foo();
    printf("wrapfoo:");__wrap_foo();
    printf("realfoo:");__real_foo();
    return 0;
}

foo.c:

#include <stdio.h>
int foo() {
    printf("foo\n");
    return 0;
}

Then compile:

gcc main.c foo.c -Wl,--wrap=foo -o main

And the the amazing output after running ./main:

foo:wrap foo
wrapfoo:wrap foo
realfoo:foo

The trick is (correct me if I am wrong) that the reference of foo() and __real_foo() is not defined at compile time. I. E. they have **undefined references" which is the requierement for the linker to link foo() to __wrap_foo() and __real_foo() to foo().

eDeviser
  • 1,605
  • 2
  • 17
  • 44