How to wrap existing function in C
Asked Answered
N

2

7

I am trying to wrap existing function.

below code is perfectly worked.

#include<stdio.h>

int __real_main();

int __wrap_main()
{
    printf("Wrapped main\n");
    return __real_main();
}

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

command:

gcc main.c -Wl,-wrap,main

output:

Wrapped main
main

So i have changed main function with temp. my goal is to wrap temp() function.

Below is the code

temp.c

#include<stdio.h>

int temp();

int __real_temp();

int __wrap_temp()
{
    printf("Wrapped temp\n");
    return __real_temp();
}

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

int main()
{
    temp();
    return 0;
}

command:

gcc temp.c -Wl,-wrap,temp

output:

temp

Wrapped temp is not printing. please guide me to wrap funciton temp.

Neelyneeoma answered 3/4, 2017 at 11:8 Comment(5)
you have to move temp() to other translation unit (.c file) if you want to use this linker hack.Ewall
You haven't defined __real_temp(). But anyway, don't do obscure things like this, it is never a good idea.Ullage
user3188346 thanks buddy its worked thanks a lotNeelyneeoma
@Ullage one doesn't need to define __real_temp, the linker does it. This feature is handy for instrumenting third party code with no sources available.Arcboutant
Is it possible to wrap the static functions?Sunwise
G
9

The manpage for ld 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.

The keyword here is undefined.

If you put the definition temp in the same translation unit as the code that uses it, it will not be undefined in the code that uses it.

You need to split the code definition and the code that uses it:

#!/bin/sh

cat > user.c  <<'EOF'
#include<stdio.h>

int temp(void);

int __real_temp(void);

int __wrap_temp()
{
    printf("Wrapped temp\n");
    return __real_temp();
}
int main()
{
    temp();
    return 0;
}
EOF

cat > temp.c <<'EOF'
#include<stdio.h>
int temp()
{
    printf("temp\n");
    return 0;
}
EOF


gcc user.c  -Wl,-wrap,temp temp.c  # OK
./a.out

Splitting the build into two separate compiles perhaps makes it clearer:

$ gcc -c user.c
$ gcc -c temp.c
$ nm user.o temp.o

temp.o:
                 U puts
0000000000000000 T temp

user.o:
0000000000000015 T main
                 U puts
                 U __real_temp
                 U temp
0000000000000000 T __wrap_temp

Now since temp is undefined in user.c, the linker can do its __real_/__wrap_magic on it.

$ gcc  user.o temp.o  -Wl,-wrap=temp
$ ./a.out
  Wrapped temp
  temp
Goebbels answered 3/4, 2017 at 11:18 Comment(2)
Thanks it worked,,, is there any method that works with visual studio ?Neelyneeoma
@venkateshkambakana I don't know. I only work on Linux.Goebbels
D
4

The answer proposed by PSCocik works great if you can split the function you want to override from the function that will call it. However if you want to keep the callee and the caller in the same source file the --wrap option will not work.

Instead you can use __attribute__((weak)) before the implementation of the callee in order to let someone reimplement it without GCC yelling about multiple definitons.

For example suppose you want to mock the world function in the following hello.c code unit. You can prepend the attribute in order to be able to override it.

#include "hello.h"
#include <stdio.h>

__attribute__((weak))
void world(void)
{
    printf("world from lib\n");
}

void hello(void)
{
    printf("hello\n");
    world();
}

And you can then override it in another unit file. Very useful for unit testing/mocking:

#include <stdio.h>
#include "hello.h"

/* overrides */
void world(void)
{
    printf("world from main.c\n");
}

int main(void)
{
    hello();
    return 0;
}
Dolliedolloff answered 3/11, 2017 at 11:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.