user3967841
user3967841

Reputation:

Exporting symbols under a different name

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

Answers (3)

3CxEZiVlQ
3CxEZiVlQ

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

Mikel Rychliski
Mikel Rychliski

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

Jean-Marc Volle
Jean-Marc Volle

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

Related Questions