Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping C++ functions with GNU linker

I like the GNU linker functionality to wrap functions a lot. I normally use it mock e.g. nondeterministic function calls like rand(). Consider the following example where I would like to write a unit test for giveMeANumber:

//number.cpp
int giveMeANumber() {
  return rand() % 6 + 1;
}

I can wrap the call to rand with the GNU linker functionality wrap like this:

//test.cpp
extern "C" int __wrap_rand(void) {
return 4;
}

void unitTest() {
  assert giveMeANumber() == 5;
}

$ g++ test.cpp -o test number.o -Xlinker --wrap=rand

Is there any way to do the same with normal C++ functions? The following does not work, I guess it is because of name mangling. But even when I try it with the mangled name it does not work.

//number.cpp
int foo() {
  //some complex calculations I would like to mock
}
int giveMeANumber() {
  return foo() % 6 + 1;
}

//test.cpp
extern "C" int __wrap_foo(void) {
return 4;
}

$ g++ test.cpp -o test number.o -Xlinker --wrap=foo
like image 530
Mike Avatar asked Dec 06 '11 15:12

Mike


1 Answers

You need to either also extern "C" the function you want to wrap (if that's possible) or you need to wrap the mangled name, e.g., __wrap__Z3foov and then pass --wrap=_Z3foov to the linker.

Getting the underscores right is a little tricky. This works for me:

$ cat x.cc
#include <iostream>
using namespace std;

int giveMeANumber();

int main() {
    cerr << giveMeANumber() << endl;
    return 0;
}

$ cat y.cc
int giveMeANumber() {
    return 0;
}

extern "C" int __wrap__Z13giveMeANumberv() {
    return 10;
}

$ g++ -c x.cc y.cc && g++ x.o y.o -Wl,--wrap=_Z13giveMeANumberv && ./a.out
10
like image 90
smparkes Avatar answered Oct 31 '22 08:10

smparkes