12

How can we replace a C standard library function with our own implementation of that function ?

For example, how can I replace strcpy() with my own implementation of strcpy() and have all calls link to the new implementations instead?

Pratik Singhal
  • 6,283
  • 10
  • 55
  • 97
Gary Gauh
  • 4,984
  • 5
  • 30
  • 43
  • Why do you want to do this? What could *possibly* be the point? – Cody Gray - on strike Feb 02 '12 at 04:44
  • Is it really worth the trouble? You would have to edit the string.h header file, whose location depends on the system and environment you are using. But I think you would be better off writing a separate function. – Shredderroy Feb 02 '12 at 04:47
  • @CodyGray, I guess, looking at FatalError's [answer](http://stackoverflow.com/questions/9107259/how-to-replace-c-standard-library-functioin#9107319), that you could replace every call in an executable to your own which prints debugging? Or something like that, I guess. Probably not good practice though. You should write a new function with a different name and change all calls. – Anthony Feb 02 '12 at 04:56
  • 1
    as @CodyGray has said, you shouldn't try to override standard library functions that have been proven to be accurate and are optimized to perfection. – ApprenticeHacker Feb 02 '12 at 06:47
  • @IntermediateHacker How about standard library functions that are buggy? [Some](http://sources.redhat.com/bugzilla/show_bug.cgi?id=10089) [bug](http://bugs.centos.org/view.php?id=3326) [reports](https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/270694) concerning `rintf()`. – Daniel Fischer Feb 02 '12 at 13:19

3 Answers3

19

At least with GCC and glibc, the symbols for the standard C functions are weak and thus you can override them. For example,

strcpy.c:

#include <string.h>
#include <stdio.h>

char * strcpy(char *dst, const char *src)
{
  char *d = dst;
  while (*src) {
    *d = *src;
    d++;
    src++;
  }
  printf("Called my strcpy()\n");

  return (dst);
}

int main(void)
{
  char foo[10];
  strcpy(foo, "hello");

  puts(foo);

  return 0;
}

And build it like this:

gcc -fno-builtin -o strcpy strcpy.c

and then:

$ ./strcpy 
Called my strcpy()
hello

Note the importance of -fno-builtin here. If you don't use this, GCC will replace the strcpy() call to a builtin function, of which GCC has a number.

I'm not sure if this works with other compilers/platforms.

FatalError
  • 52,695
  • 14
  • 99
  • 116
  • 1
    Fun fact, my `strcpy()` above has a pretty serious flaw. Since it's not really the focuse here, I'll leave that as an exercise for the reader ;). – FatalError Feb 02 '12 at 04:54
  • 3
    That's sort of the point, though. Replacing the tried-and-true library functions with one of your own is almost 100% guaranteed to have serious flaws. – Cody Gray - on strike Feb 02 '12 at 04:58
  • As for the flaw: in this version of `strcpy()`, the loop condition will never be false if `src` and `dst` are overlapping. – Philip Feb 02 '12 at 08:20
  • 6
    I don't think `strcpy()` was *ever* guaranteed against overlapping strings. However, it *is* guaranteed to nul-terminate dst ;). – FatalError Feb 02 '12 at 12:29
7

You can try playing with LD_PRELOAD if you are on Linux.

shadyabhi
  • 16,675
  • 26
  • 80
  • 131
  • This seems to be the right way. [Here](https://github.com/nibrahim/Random-hacks/tree/master/malloc-trace) is an example but the real question is why? – Noufal Ibrahim Feb 02 '12 at 04:48
  • This is called interposing a library. You have to create a C module that is compiled as PIC (position independent code) into a .so file. Then you set LD_PRELOAD=/path/to/mystrcpy.so You can also accomplish the same thing by calling dl_open() in your code. It is easier simply to create mystrcpy.c compile that into an object module and call that everywhere else in your code, and link to the mystrcpy object module. You will have to use an extern declaration for mystrcpy everywhere as well. see: http://stackoverflow.com/questions/426230/what-is-the-ld-preload-trick – jim mcnamara Feb 02 '12 at 04:57
6

I'm not sure how hard it will be to get the linker to do what you want, but here's a solution that doesn't involve changing any linker settings and uses preprocessor macros instead so that any code that tries to call strcpy actually calls a function called my_strcpy:

mystuff.h:

#define strcpy my_strcpy
char * my_strcpy(char * dst, const char * src);

my_strcpy.c:

#include <mystuff.h>
char * my_strcpy(char * dst, const char * src);
{
    ...
}

my_code.c:

#include <mystuff.h>

int main()
{
   /* Any call to strcpy will look like a normal call to strcpy
      but will actually call my_strcpy. */
}
David Grayson
  • 84,103
  • 24
  • 152
  • 189