LD_PRELOAD can be used to link a shared object before the other.So I try to override memcpy in glibc.
I define my memcpy which will reverse the byte order of src and return NULL to distinguish with glibc's memcpy
mymem.c
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n) {
char *dest_c = dest;
const char *src_c = src;
size_t i = 0;
//reverse the byte order in src
for(i = 0; i < n; i++)
dest_c[i] = src_c[n-i-1];
return NULL;
}
test.c
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "hello";
char str2[100] = {};
char *ret;
//print the address of str2
printf("str2: %p\n", str2);
//print str2, address of memcpy, return value of memcpy
ret = memcpy(str2, str, 6);
printf("%s %p %p\n", str2, memcpy, ret);
//the same
ret = memcpy(str2, str, 3);
printf("%s %p %p\n", str2, memcpy, ret);
//the same
ret = memcpy(str2, str, 8);
printf("%s %p %p\n", str2, memcpy, ret);
return 0;
}
compile & run:
$gcc -shared -o libmem.so mymem.c
$gcc test.c -o test
$export LD_PRELOAD="./libmem.so"
$./test
the result:
str2: 0x7fff0297e710
hello 0x400470 0x7fff0297e710
lehlo 0x400470 (nil)
0x400470 (nil)
the output is not as I expected when the third param equals the size of the char array(In this case, sizeof str is 6).
after the first memcpy, I think str2[0] should be '\0', so str2 is an empty string, but the output is "hello". and the return value of memcpy should be NULL, but the output is the address of str2. It looks like the glic's memcpy works(I am not sure).
the other two memcpy works as I expected.
I haved test it in debian 8 and ubuntu 14.04.
Can someone explain it?
It's because for some reason GCC decides to use an inlined version of memcpy
in for the first call to memcpy
. To avoid that you could use the -fno-builtin
option.
Also note that if for some reason memcpy
gets statically linked into the executable, it could result in that memcpy
being resolved statically. As memcpy
is such a low-level function it's not impossible that the implementation could have been provided by CRT-startup code (which is linked statically).