在 linux 中可以通过设置 LD_PRELOAD 环境变量来优先加载指定的动态库,详情请见:https://www.man7.org/linux/man-pages/man8/ld.so.8.html。下面就记录一下它的基本用法——使用 LD_PRELOAD 旁路 libc 中的 memcmp。
1)实现自己的 memcmp(为提高效率,先以 8 字节块为大小进行比较,失配后进行逐字节比较)
memcmp.c 的内容如下:
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
int memcmp(const void *s1, const void *s2, size_t count)
{
uint64_t *p = (uint64_t *)s1;
uint64_t *q = (uint64_t *)s2;
unsigned char *str1 = (unsigned char *)s1;
unsigned char *str2 = (unsigned char *)s2;
size_t i = 0;
printf("%s:%d\n", __func__, __LINE__);
while (count >= 8) {
if (p[i] != q[i]) {
break;
}
++i;
count -= 8;
}
str1 = (unsigned char *)&p[i];
str2 = (unsigned char *)&q[i];
i = 0;
while (count > 0) {
if (str1[i] != str2[i])
return str1[i] > str2[i] ? 1 : -1;
++i;
--count;
}
return 0;
}
2)编译动态库
$ gcc -O3 -shared -fPIC -o libmemcmp.so memcmp.c
3)编写调用程序
main.c 的内容如下:
#include <stdio.h>
#include <stddef.h>
extern int memcmp(const void *str1, const void *str2, size_t count);
int main(void)
{
unsigned char str1[] = "01001110001100000";
unsigned char str2[] = "01001110001100001";
int ret;
ret = memcmp(str1, str2, sizeof(str1));
printf("compare result: %d\n", ret);
return 0;
}
4)设置 LD_PRELOAD
$ export LD_PRELOAD=./libmemcmp.so
5)运行调用程序
$ ./main
memcmp:13
compare result: -1