Reputation:
My situation is as follows: I need to build a library where I export a "wrapped" strcpy
(please ignore how that is useful to me) which the only thing it does is call the standard (from string.h
) strcpy
but return void
, instead of returning char *
. Which means, I need to #include string.h
but this will immediately give me strcpy
and gcc
won't let me re-define it as I wish, and build a .so
shared library exporting only the new, wrapped strcpy
. How can I accomplish that?
Upvotes: 0
Views: 574
Reputation: 38465
mystring.h
extern "C" void strcpy(char* dst, const char* src);
stringinternal.h
void mystrcpy(char* dst, const char* src);
mystring.c
#include "mystring.h"
#include "stringinternal.h"
extern "C" void strcpy(char* dst, const char* src) {
mystrcpy(dst, src);
}
stringinternal.c
#include "stringinternal.h"
#include <string.h>
void mystrcpy(char* dst, const char* src) {
strcpy(dst, src);
}
main.c
#include "mystring.h"
int main() {
char dst[3];
strcpy(dst, "ab");
return 0;
}
The standard strcpy
is exported as a weak function and you can redefine it in your library.
For proper link your .so you have to disable standard libraries for linkage and list files in a proper order: strcpyinternal.o then required standard libs and mystring.o in the end. This will prevent from recursive strcpy call from your .so. Example for gcc can be like
gcc -shared -nostdlib -o my.so stringinternal.o -lc mystring.o
Upvotes: 1
Reputation: 3597
strcpy
is a weak symbol with "C" linkage, so it's possible to override without errors
libstrcpy.cc:
#include <dlfcn.h>
extern "C" {
void strcpy(char *dest, char *src)
{
auto real_strcpy = (char*(*)(char*,char*)) dlsym(RTLD_NEXT, "strcpy");
real_strcpy(dest, src);
}
}
Compile with: g++ libstrcpy.cc -std=c++11 -shared -fPIC -ldl -o libstrcpy.so
Verify strcpy
export: readelf --dyn-syms libstrcpy.so
To use (main.cc):
extern "C"{
void strcpy(char *, char *);
}
int main()
{
char a[10] = "test" , b[10] = {};
strcpy(a, b);
}
Compile with: g++ main.cc -o main -lstrcpy -L./
Note that if you want to use the correct void
returning declaration, you can't import any header that will define strcpy
(the right way).
Upvotes: 0
Reputation: 3323
If you uses c++, you can define your own namespace eg:
in a my.h
namespace strcpy_v2
{
void strcpy( char *dest, const char *src );
}
in the associated my.cpp
#include <string>
#include "my.h"
void strcpy_v2::strcpy( char *dest, const char *src )
{
auto val = std::strcpy(dest,src);
// you should test val to ensure every thing is ok
}
The from the code that will link you .so. You can do:
using namespace strcpy_v2;
instead of
using namespace std;
Upvotes: 0