Home > Net >  How can I hook a static function?
How can I hook a static function?

Time:12-22

I'm trying to mock a static function without modifying the source code. This is because we have a large legacy base of code and we would like to add test code without requiring developers to go through and change a bunch of the original code.

Using objcopy, I can play with functions between object files, but I can't affect internal linkages. In other words, in the code below, I can get main.cpp to call a mocked up foo() from bar.c, but I cannot get UsesFoo() to call the mocked up foo() from bar.c.

I understand this is because foo() is already defined within foo.c. Aside from changing the source code, is there any way I can use ld or another tool to rip out foo() so that final linking pulls it in from my bar.c?

foo.c

#include <stdio.h>

static void foo()
{
    printf("static foo\n");
}

void UsesFoo()
{
    printf("UsesFoo(). Calling foo()\n");
    foo();
}

bar.c

#include <stdio.h>

void foo()
{
    printf("I am the foo from bar.c\n");
}

main.cpp

#include <iostream>

extern "C" void UsesFoo();
extern "C" void foo();

using namespace std;

int main()
{
    cout << "Calling UsesFoo()\n\n";
    UsesFoo();
    cout << "Calling foo() directly\n";
    foo();
    return 0;
}

compiling:

gcc -c foo.c
gcc -c bar.c
g   -c main.c
(Below simulates how we consume code in the final output)
ar cr libfoo.a foo.o
ar cr libbar.a bar.o
g   -o prog main.o -L. -lbar -lfoo
This works because the foo() from libbar.a gets included first, but doesn't affect the internal foo() in foo.o

I have also tried:

gcc -c foo.c
gcc -c bar.c
g   -c main.c
(Below simulates how we consume code in the final output)
ar cr libfoo.a foo.o
ar cr libbar.a bar.o
objcopy --redefine-sym foo=_redefinedFoo libfoo.a libfoo-mine.a
g   -o prog main.o -L. -lbar -lfoo-mine
This produces the same effect. main will call foo() from bar, but UsesFoo() still calls foo() from within foo.o

CodePudding user response:

The usual trick is to compile them as shared libraries and then use LD_PRELOAD to preload a version that will replace the functions you are targeting.

Here is a decent tutorial:

https://catonmat.net/simple-ld-preload-tutorial

CodePudding user response:

I think you can try --wrap flag in gcc. An example for using the flag: How to wrap functions with the `--wrap` option correctly?

  • Related