Is there a simple way to specify alternative functions (to the linker) to be used rather than the standard ones?
I have a wrapper around open/close/read/write system functions. I can test the functionality of the good path for these functions relatively easily.
But testing the potential errors is harder. To do this I need to get open/close/read/write to generate specific error codes for each test. Is there a way to link in alternative versions of these functions that I can then program to set the appropriate errno value before returning?
The linker option --wrap is for this purpose.
Some code that calls open:-
main.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define N 32
int main(int argc, char *argv[])
{
char buf[N] = {0};
int fd = open(argv[1],O_RDONLY);
read(fd,buf,N - 1);
puts(buf);
close(fd);
return 0;
}
For simplicity it's a program, but it needn't be.
Using the true open:
$ gcc -Wall -c main.c
$ gcc -o prog main.o
$ echo "Hello world" > hw.txt
$ ./prog hw.txt
Hello world
Your alternative open must be called __wrap_open, and
must refer to the real open, if it needs to, as __real_open:
dbg_open.c
#include <stdio.h>
extern int __real_open(const char *path, int oflag);
int __wrap_open(const char *path, int oflag)
{
printf("In tester %s\n",__FUNCTION__);
return __real_open(path,oflag);
}
There's no need to recompile main.c to replace open with __wrap_open in prog; just
reuse main.o in a different linkage of prog
$ gcc -Wall -c dbg_open.c
$ gcc -o prog main.o dbg_open.o -Wl,--wrap=open
$ ./prog hw.txt
In tester __wrap_open
Hello world
If your __wrap_foo alternatives needed to knock out C++ functions
foo then you would need to obtain the mangling of foo to specify in the linkage
option --wrap=mangled-foo. But since you want to knock out system calls
you're spared that complication.
Related
I am trying to implement some unit tests for a C++ library that does not use OO (all functions are declared at namespace level)
For that purpose, I am trying to create a test binary that mocks (simulate) some functions.
I have achieved the above for functions that I call directly, but I have been unable to replace the calls that the library's functions do. The example below explains this:
Production code
Lets suppose this is the production code, the one that uses the real functions instead of the simulated ones:
CameraHandler.H
namespace Cam {
int myFunc();
int myFunc2();
}
CameraHandler.cpp
#include "CameraHandler.h"
using namespace Cam;
int Cam::myFunc() {
// Imagine this is the function I want to simulate with a mock
// Its mangled name is _ZN3Cam6myFuncEv
return 1;
}
int Cam::myFunc2(){
return Cam::myFunc() + 11;
}
Testing code
This is the code for the unit testing. As you can see in the Makefile, it generates a binary called testsMain.
CameraHandlerMock.h
extern "C" {
int __wrap__ZN3Cam6myFuncEv(); // mangled name of Cam::myFunc(), with the __wrap_ prefix.
}
CameraHandlerMock.cpp
#include "CameraHandlerMock.h"
int __wrap__ZN3Cam6myFuncEv(){
// As you can see, the mocked function returns 999 instead of 1.
return 999;
}
UnitTestsMain.cpp
#include <iostream>
#include <typeinfo>
#include "CameraHandler.h"
#include "CameraHandlerMock.h"
extern "C" int _ZN3Cam6myFuncEv();
int main(){
std::cout << Cam::myFunc() << std::endl;
std::cout << Cam::myFunc2() << std::endl;
return 0;
}
The Makefile
WRAP=-Wl,--wrap,_ZN3Cam6myFuncEv
all: production unitTests
production: // does not matter for this example
g++ main.cpp CameraHandler.cpp -o main
unitTests:
g++ ${WRAP} UnitTestsMain.cpp CameraHandlerMock.cpp CameraHandler.cpp -o testsMain
The problem
If I execute the testsMain program, I obtain the following result:
999 // call to Cam::myFunc()
12 // Cam::myFunc2(), which is Cam::myFunc() + 11.
Taking into account that Cam::myFunc2() calls to Cam::myFunc1(), and I have replaced it by __wrap__ZN3Cam6myFuncEv, what I expect is that t he result of calling Cam::myFunc2() is 999 + 11 = 1010. Nevertheless, Cam::myFunc2() is still calling the non-wrapped Cam::myFunc1(), so the result is 12.
Is there any way to wrap functions that are internally called by the library I want to test?
Let's lint a little bit of fluff first. In UnitTestsMain.cpp,
the declaration:
extern "C" int _ZN3Cam6myFuncEv();
is redundant. It simply instructs the C++ compiler that references to the function
of that prototype whose mangled name is _ZN3Cam6myFuncEv are references to
an externally defined function of that name. This is exactly the same information,
just expressed differently, that that the compiler has already got from:
namespace Cam {
int myFunc();
...
}
when it #include-ed CameraHandler.h, because _ZN3Cam6myFuncEv() is the mangled
form of Cam::myFunc. The extern "C" redeclaration of Cam::myFunc is harmless
but contributes nothing either to compilation or linkage.
On to the main question: Why does your mock
int __wrap__ZN3Cam6myFuncEv() get called instead of int Cam::myFunc in UnitTestsMain.cpp:
int main(){
std::cout << Cam::myFunc() << std::endl;
std::cout << Cam::myFunc2() << std::endl;
return 0;
}
as you want; but your mock is not called for int Cam::myFunc in CameraHandler.cpp:
int Cam::myFunc2(){
return Cam::myFunc() + 11;
}
The answer lies in the documentation of the --wrap linker option:
--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.
Maybe you read it and didn't grok the significance of undefined reference.
This means that when --wrap=symbol is in effect, and the linker applies it
to an object file containing undefined references to symbol, it will replace them
with references to __wrap_symbol, and undefined references to __real_symbol,
in that object file, will be replaced with symbol.
Now in UnitTestsMain.o, compiled from UnitTestsMain.cpp, the references to both Cam::myFunc()
and Cam::myFunc2() are undefined. These functions are both defined in CameraHandler.cpp,
compiled in CameraHandler.o.
Therefore in the linkage of UnitTestsMain.o, --wrap ZN3Cam6myFuncEv will take effect and
replace the call to Cam::myFunc ( = ZN3Cam6myFuncEv) with a call to __wrap_ZN3Cam6myFuncEv.
The call to Cam::myFunc2() ( = ZN3Cam7myFunc2Ev) is not wrapped and is unaffected: it will be
resolved to the definition to be found in CameraHandler.o
But in the linkage of CameraHandler.o, both functions are defined, so --wrap has
no effect. When Cam::myFunc2() calls Cam::myFunc(), it calls ZN3Cam6myFuncEv, not
__wrap_ZN3Cam6myFuncEv.
That explains why the program outputs:
999
12
and not:
999
1010
Can you make your mocking work as expected?
Yes. You just have to ensure that every call to Cam::myFunc that you want to be
mocked is compiled into an object file that does not contain the (real) definition
of Cam::myFunc. The obvious way to do that is to define Cam::myFunc in its own
source file. Here's your example fixed:
CameraHandler.h
#ifndef CAMERAHANDLER_H
#define CAMERAHANDLER_H
namespace Cam {
int myFunc();
int myFunc2();
}
#endif
CameraHandlerMock.h
#ifndef CAMERAHANDLERMOCK_H
#define CAMERAHANDLERMOCK_H
extern "C" {
int __wrap__ZN3Cam6myFuncEv();
}
#endif
CameraHandler_myFunc.cpp
#include "CameraHandler.h"
using namespace Cam;
int Cam::myFunc() {
return 1;
}
CameraHandler_myFunc2.cpp
#include "CameraHandler.h"
using namespace Cam;
int Cam::myFunc2(){
return Cam::myFunc() + 11;
}
CameraHandlerMock.cpp
#include "CameraHandlerMock.h"
int __wrap__ZN3Cam6myFuncEv() {
return 999;
}
UnitTestsMain.cpp
#include <iostream>
#include "CameraHandler.h"
#include "CameraHandlerMock.h"
int main(){
std::cout << Cam::myFunc() << std::endl;
std::cout << Cam::myFunc2() << std::endl;
return 0;
}
Makefile
SRCS := UnitTestsMain.cpp CameraHandler_myFunc.cpp \
CameraHandler_myFunc2.cpp CameraHandlerMock.cpp
OBJS := $(SRCS:.cpp=.o)
LDFLAGS := -Wl,--wrap,_ZN3Cam6myFuncEv
.PHONY: unitTests clean
unitTests: testsMain
testsMain: $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
UnitTestsMain: CameraHandler.h CameraHandlerMock.h
CameraHandler_Func.o CameraHandler_Func2.o: CameraHandler.h
CameraHandlerMock.o: CameraHandlerMock.h
clean:
rm -f $(OBJS) testsMain
(Your production build is not considered at all in this example makefile)
With this, the test build runs like:
$ make
g++ -c -o UnitTestsMain.o UnitTestsMain.cpp
g++ -c -o CameraHandler_myFunc.o CameraHandler_myFunc.cpp
g++ -c -o CameraHandler_myFunc2.o CameraHandler_myFunc2.cpp
g++ -c -o CameraHandlerMock.o CameraHandlerMock.cpp
g++ -Wl,--wrap,_ZN3Cam6myFuncEv -o testsMain UnitTestsMain.o \
CameraHandler_myFunc.o CameraHandler_myFunc2.o CameraHandlerMock.o
and testsMain does what you expect:
$ ./testsMain
999
1010
You can simplify both source files and the makefile somewhat if you rewrite
CameraHandlerMock.cpp as just:
extern "C" {
int __wrap__ZN3Cam6myFuncEv() {
return 999;
}
}
Then you have no need for the mock header file CameraHandlerMock.h at all.
If you have a lot of functions you need to mock in this low-level way, it
may get tedious to define each one in its own source file. You may be aware
that there are higher-level, framework-supported mocking options, e.g. googlemock,
that have rich mocking capabilities and don't entail this tedium. It's fair to say, however, that they may
replace it with more complicated kinds of tedium.
I have two versions of a a shared library:
library version 2:
simple.h
#pragma once
int first(int x);
simple.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first#LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first##LIBSIMPLE_2.0");
int first_2_0(int x)
{
int y;
printf("lib: %d\n", y);
printf("lib: %s\n", __FUNCTION__);
return (x + 1) * 1000;
}
linker version script file:
LIBSIMPLE_1.0{
global:
first;
local:
*;
};
LIBSIMPLE_2.0{
global:
first;
local:
*;
};
gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.2.0.0
And library version 3:
simple.h
#pragma once
#ifdef SIMPLELIB_VERSION_3_0
int first(int x, int normfactor);
#else
int first(int x);
#endif //SIMPLELIB_VERSION_3_0
simple.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first#LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first#LIBSIMPLE_2.0");
int first_2_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return (x + 1) * 1000;
}
__asm__(".symver first_3_0,first##LIBSIMPLE_3.0");
int first_3_0(int x, int normfactor)
{
printf("lib: %s\n", __FUNCTION__);
return (x + 1) * normfactor;
}
Linker version script file:
LIBSIMPLE_1.0{
global:
first; second;
local:
*;
};
LIBSIMPLE_2.0{
global:
first;
local:
*;
};
LIBSIMPLE_3.0{
global:
first;
local:
*;
};
gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.3.0.0
So i end up with having two different libraries. Next i create a simple application, that eventually i want to link to a library version 3, so in it i use function first() that takes two arguments:
main.c
#include <stdio.h>
#include "simple.h"
int main(int argc, char* argv[])
{
int nFirst = first(1, 10);
printf("First(1) = %d\n", nFirst);
}
I compile app with next commands:
gcc -g -Wall -DSIMPLELIB_VERSION_3_0 -c main.c
And then, by accident, instead of linking to a library version 3, i linked against library version 2. I expected linking to fail, but it went through, and application was working.
gcc main.o -Wl,-L. -lsimple.2.0.0 -Wl,-R. -o demo
So my questions are:
Is it because library exports symbol with name 'function', and application tries to link to the same symbol name, and that is why linker didn't complain, and just linked against library version 2 ?
I thought since c++ mangles symbol names, such thing wouldn't happen, and linker wouldn't link to a library version 2. So i tried all the same, but instead of a gcc compiler, i tried to use g++. Everything went well, until i tried to link application to a library, and i received unresolved links error. Can not figure out why.
p.s. Sorry for a big amount of code. I was trying to make it clear.
Thanks
Is it because library exports symbol with name 'function', and application tries to link to the same symbol name, and that is why linker didn't complain, and just linked against library version 2 ?
Yes, since plain C does not have function overload there is no need for mangling and as a consequence only function name will be used as a symbol for linking. In the end your application code wants to link with function and your library code exports function and this is enough to keep linker happy (even though it is not valid from binary interface perspective).
I thought since c++ mangles symbol names, such thing wouldn't happen, and linker wouldn't link to a library version 2. So i tried all the same, but instead of a gcc compiler, i tried to use g++. Everything went well, until i tried to link application to a library, and i received unresolved links error. Can not figure out why.
Yes, this problem should not occur in C++ because of name mangling. However, this is true only if you have both your application code and library code in C++ or if you bridge your C and C++ code the right way.
It is hard to say (without full listing) what happened in your case when you used g++ but from the looks of it you ended up having application code in C++ and library code still in C. If that is the case your application code will now want to link with mangled function while your library code still exports unmangled function.
To verify this you can inspect your object file with something like:
nm main.o
... and see exactly what kind of symbol does it want. If you will get something like this:
...
U _Z3functionii
...
... instead of:
...
U function
...
... then that is the case.
To "fix" this and make your C++ application code link with unmangled function from library code you'll need to declare your function prototype as extern "C".
Obviously something goes wrong with my understanding of this topic, but I can't find out where. The thing I want to implement is a custom Exception called CustomException. What I have made does compile and can work, but I do think that I am making use of header files the wrong way. So I have made the following 3 files:
main.cpp
#include "exception.h"
int main() {
try {
throw CustomException();
} catch (CustomException ce) {
ce.doSomething();
}
}
exception.h
#include <exception>
class CustomException : public std::exception {
private:
char* msg;
public:
CustomException() {};
void doSomething() {};
};
exception.cpp
#include "exception.h"
CustomException::CustomException() {
}
void CustomException::doSomething() {
printf("Hello World!");
}
After I run this is the command line:
$ g++ main.cpp -o main.o
$ ./main.o
$
But the behaviour that I was looking for is, that "Hello World!" is printed to the command line. I am more used to JAVA, so maybe that is why I have a rough start with C++. Anyways I hope you can help me, because the tutorials I found differ from each other and don't make sense to me.
Your problem is that you're defining CustomException::doSomething() to do nothing: {}. Leave out the {} method definitions in exception.h. Then compile and link exception.cpp into your binary:
$ g++ -c main.cpp -o main.o
$ g++ -c exception.cpp -o exception.o
$ g++ main.o exception.o -o main
$ ./main
Note that a ".o" suffix is normally used for object files, not for executables.
In addition to what user3553031 said, there is another posslble problem with your code. In C++ you should catch exceptions by reference, not by value. Otherwise it can cause problems. See this: C++ catch blocks - catch exception by value or reference?
I have scenario where I have a binary that depends on library A which in turn depends on library B.
I have built library A against library B, but none of library B:s symbols leak out of library A, everything is contained in the cpp-file.
Now I only want to link the binary against library A, since all of the symbols found in the binary can be satisfied by library A. Is this possible?
In the real application, library B is an implementation of a network protocol and I have a lot of binaries who link against the intermediate library. And I don't want the binaries to be aware of the different network protocols used.
Platform: Linux / GCC
Code:
liba/liba.h:
#ifndef LIBA_H
#define LIBA_H
int getANumber();
#endif
liba/liba.cpp:
#include "liba.h"
#include "../libb/libb.h"
int getANumber(){ return getBNumber(); }
libb/libb.h:
#ifndef LIBB_H
#define LIBB_H
int getBNumber();
#endif
libb/libb.cpp:
#include "libb.h"
int getBNumber(){ return 42; }
main.cpp:
#include "liba/liba.h"
#include <iostream>
int main(int argc, char** argv) {
std::cout << getANumber() << std::endl;
return 0;
}
commands:
~/libb/ $ g++ -shared -o libb.so libb.cpp
~/liba/ $ g++ -shared -o liba.so liba.cpp -L../libb -lb
~/ $ g++ -o main main.cpp -Lliba -la # fails
~/ # These two work, but I don't want to specify libb here.
~/ $ g++ -o main main.cpp -Lliba -la -Wl,-rpath-link,libb
~/ $ LD_LIBRARY_PATH=libb g++ -o main main.cpp -Lliba -la
What is the best way to solve this? Do I have to create it as a plugin?
Best regards,
Daniel
If you want to CHANGE which library you use at runtime, then you can't link against it directly, but use a "manual" loading. In other words, call dlopen and dlsym
This probably also means that you need a slightly different architecture in "liba", since each function in "libb" becomes a function pointer, so something along these lines:
int (*getBNumber)() = NULL;
void initialize()
{
void *handle = dlopen("libb", RTLD_NOW);
getBNumber = (int (*)())dlsym(handle, "getBNumber");
}
int getANumber(){ return getBNumber(); }
You'll need to set something up to call initialize at some point - or have a if (!initialized) initialize(); in each function.
I have an application that statically links with version X of a library, libfoo, from thirdparty vendor, VENDOR1. It also links with a dynamic (shared) library, libbar, from a different thirdparty vendor, VENDOR2, that statically links version Y of libfoo from VENDOR1.
So libbar.so contains version Y of libfoo.a and my executable contains version X of libfoo.a
libbar only uses libfoo internally and there are no libfoo objects passed from my app to libbar.
There are no errors at build time but at runtime the app seg faults. The reason seems to be that version X uses structures that have a different size they version Y and the runtime linker seems to be mixing up which get used by which.
Both VENDOR1 & VENDOR2 are closed source so I cannot rebuild them.
Is there a way to build/link my app such that it always resolves to version X and libbar alway resolves to version Y and the two never mix?
Thanks for all the responses. I have a solution that seem to be working.
Here's the problem in detail with an example.
In main.c we have:
#include <stdio.h>
extern int foo();
int bar()
{
printf("bar in main.c called\n");
return 0;
}
int main()
{
printf("result from foo is %d\n", foo());
printf("result from bar is %d\n", bar());
}
In foo.c we have:
extern int bar();
int foo()
{
int x = bar();
return x;
}
In bar.c we have:
#include <stdio.h>
int bar()
{
printf("bar in bar.c called\n");
return 2;
}
Compile bar.c and foo.c:
$ gcc -fPIC -c bar.c
$ gcc -fPIC -c foo.c
Add bar.o to a static library:
$ ar r libbar.a bar.o
Now create a shared library using foo.o and link with static libbar.a
$ gcc -shared -o libfoo.so foo.o -L. -lbar
Compile main.c and link with shared library libfoo.so
$ gcc -o main main.c -L. -lfoo
Set LD_LIBRARY_PATH to find libfoo.so and run main:
$ setenv LD_LIBRARY_PATH `pwd`
$ ./main
bar in main.c called
result from foo is 0
bar in main.c called
result from bar is 0
Notice that the version of bar in main.c is called, not the version linked into the shared library.
In main2.c we have:
#include <stdio.h>
#include <dlfcn.h>
int bar()
{
printf("bar in main2.c called\n");
return 0;
}
int main()
{
int x;
int (*foo)();
void *handle = dlopen("libfoo.so", RTLD_GLOBAL|RTLD_LAZY);
foo = dlsym(handle, "foo");
printf("result from foo is %d\n", foo());
printf("result from bar is %d\n", bar());
}
Compile and run main2.c (notice we dont need to explicitly link with libfoo.so):
$ gcc -o main2 main2.c -ldl
$ ./main2
bar in bar.c called
result from foo is 2
bar in main2.c called
result from bar is 0
Now foo in the shared library calls bar in the shared library and main calls bar in main.c
I don't think this behaviour is intuitive and it is more work to use dlopen/dlsym, but it does resolve my problem.
Thanks again for the comments.
Try a partial link so that you have an object file "partial.o" with libbar and libfoo-Y. Use objcopy with "--localize-symbols " to make the symbols in partial.o from libfoo-Y local. You should be able to generate by running nm on libfoo-Y and massaging the output. Then take the modified partial.o and link it to your app.
I've done something similar with gcc toolchain on vxWorks where dynamic libs are not a complication but two versions of the same lib needed to link cleanly into a monolithic app.
Sorry no. My understanding of the way that Linux (and possibly most *nixes) is that that is not possible. The only 'solution' for your problem I can think of, is if you create a proxy app, which exposes what you need from libbar in the form of some IPC. You can then make that proxy load the correct version using LD_LIBRARY_PATH or something simmilar.