C LD_PRELOAD如何在我的代码中工作
LD_PRELOAD可以用来在一个共享对象之前链接另一个共享对象,所以我尝试在glibc中重写memcpy 我定义了memcpy,它将反转src的字节顺序,并返回NULL以区别于glibc的memcpy mymem.cC LD_PRELOAD如何在我的代码中工作,c,ld,glibc,C,Ld,Glibc,LD_PRELOAD可以用来在一个共享对象之前链接另一个共享对象,所以我尝试在glibc中重写memcpy 我定义了memcpy,它将反转src的字节顺序,并返回NULL以区别于glibc的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; s
#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;
}
结果是:
str2: 0x7fff0297e710
hello 0x400470 0x7fff0297e710
lehlo 0x400470 (nil)
0x400470 (nil)
当第三个参数等于char数组的大小(在本例中,sizeof str为6)时,输出不是我所期望的
在第一个memcpy之后,我认为str2[0]应该是'\0',因此str2是一个空字符串,但输出是“hello”。memcpy的返回值应该为NULL,但输出是str2的地址。看起来glic的memcpy可以工作(我不确定)
另外两个memcpy的工作方式与我预期的一样
我已经在Debian8和Ubuntu14.04中进行了测试
有人能解释一下吗?这是因为出于某种原因,GCC决定在第一次调用
memcpy
时使用memcpy
的内联版本。为了避免这种情况,您可以使用-fno-builtin
选项
还要注意,如果出于某种原因,
memcpy
静态链接到可执行文件中,则可能导致该memcpy
被静态解析。由于memcpy
是一个低级函数,CRT启动代码(静态链接)提供实现并非不可能。只需在二进制文件上执行objdump-DS
(正如qarma已经建议的),您就可以看到您的第一个memcpy
不会生成函数调用。这是它在我的机器上的外观:
//print str2, address of memcpy, return value of memcpy
ret = memcpy(str2, str, 6);
40066e: 8b 85 70 ff ff ff mov -0x90(%rbp),%eax
400674: 89 45 80 mov %eax,-0x80(%rbp)
400677: 0f b7 85 74 ff ff ff movzwl -0x8c(%rbp),%eax
40067e: 66 89 45 84 mov %ax,-0x7c(%rbp)
400682: 48 8d 45 80 lea -0x80(%rbp),%rax
400686: 48 89 85 68 ff ff ff mov %rax,-0x98(%rbp)
尝试使用-fno内置memcpy编译-它应该可以解决以下问题:
ret = memcpy(str2, str, 6);
40066e: 48 8d 8d 70 ff ff ff lea -0x90(%rbp),%rcx
400675: 48 8d 45 80 lea -0x80(%rbp),%rax
400679: ba 06 00 00 00 mov $0x6,%edx
40067e: 48 89 ce mov %rcx,%rsi
400681: 48 89 c7 mov %rax,%rdi
400684: e8 87 fe ff ff callq 400510 <memcpy@plt>
400689: 48 89 85 68 ff ff ff mov %rax,-0x98(%rbp)
ret=memcpy(str2,str,6);
40066e:48 8d 8d 70 ff ff ff lea-0x90(%rbp),%rcx
400675:48 8d 45 80 lea-0x80(%rbp),%rax
400679:ba 06 00 mov$0x6,%edx
40067e:48 89 ce mov%rcx%rsi
400681:48 89 c7 mov%rax,%rdi
400684:e8 87 fe ff ff callq 400510
400689:48 89 85 68 ff ff移动百分比rax,-0x98(%rbp)
memcpy
可以通过“内在”进行内联或实现--请运行nm-D您的\u二进制文件
进行验证。此外,printf
可能在内部使用memcpy
,这使年轻人的测试变得非常复杂:)请重载一些罕见的函数,或者重载外部副作用(与可逆数据损坏相反)
//print str2, address of memcpy, return value of memcpy
ret = memcpy(str2, str, 6);
40066e: 8b 85 70 ff ff ff mov -0x90(%rbp),%eax
400674: 89 45 80 mov %eax,-0x80(%rbp)
400677: 0f b7 85 74 ff ff ff movzwl -0x8c(%rbp),%eax
40067e: 66 89 45 84 mov %ax,-0x7c(%rbp)
400682: 48 8d 45 80 lea -0x80(%rbp),%rax
400686: 48 89 85 68 ff ff ff mov %rax,-0x98(%rbp)
ret = memcpy(str2, str, 6);
40066e: 48 8d 8d 70 ff ff ff lea -0x90(%rbp),%rcx
400675: 48 8d 45 80 lea -0x80(%rbp),%rax
400679: ba 06 00 00 00 mov $0x6,%edx
40067e: 48 89 ce mov %rcx,%rsi
400681: 48 89 c7 mov %rax,%rdi
400684: e8 87 fe ff ff callq 400510 <memcpy@plt>
400689: 48 89 85 68 ff ff ff mov %rax,-0x98(%rbp)