[英]Global variable in shared pic library has different access way in 32 and 64 bits binary, as well as its locations?
Recently I took a look into how plt and got implemented, and wrote a chunk of sample code for tracing as below. 最近,我研究了plt的实现方式,并编写了以下示例代码以进行跟踪。 And something I saw confused me a lot. 我看到的东西让我很困惑。
got.c 得到了
#include <stdio.h>
static int static_data;
int global_data;
extern int count;
int
main(void)
{
static_data = 12;
global_data = 32;
add_count();
count += static_data;
count += global_data;
printf("error, %p\n", &count);
return count;
}
extern.c 外部
#include <errno.h>
#include <stdio.h>
int count = 0x1;
void
add_count(void)
{
errno = 0xdead;
count += errno;
fprintf(stdout, "%p\n", &count);
fprintf(stdout, "%p\n", &count);
fprintf(stdout, "%p\n", &count);
}
and compile it like this: 并像这样编译它:
gcc -shared -fpic extern.c -o extern.so
sudo cp extern.so /lib/libextern.so
gcc -g got.c -o got.bin -lextern
question 1: why global variable address of count in libextern.so is 0x601048 ? 问题1:为什么libextern.so中count的全局变量地址为0x601048?
question 2: for external symbol, use .plt and .got.plt for lazy binding, but for global variable like count, why 32-bits use get_pc_thunk for reference .got, and 64-bits just 0xXXX(%rip) for addressing .got ? 问题2:对于外部符号,请使用.plt和.got.plt进行延迟绑定,但对于诸如count之类的全局变量,为什么32位使用get_pc_thunk引用.got,而64位仅使用0xXXX(%rip)进行寻址。得到 ? Or 32-bit can use this rip + offset way for addressing .got of libextern.so ? 或者32位可以使用这种rip + offset方法来解决libextern.so的.got吗?
Thanks in advance! 提前致谢!
when -m32 compiled function add_count: 当-m32编译函数add_count时:
550 5bf: 83 ec 14 sub $0x14,%esp
551 5c2: e8 c9 fe ff ff call 490 <__x86.get_pc_thunk.bx>
552 5c7: 81 c3 39 1a 00 00 add $0x1a39,%ebx
553 5cd: e8 ae fe ff ff call 480 <__errno_location@plt>
554 5d2: c7 00 ad de 00 00 movl $0xdead,(%eax)
555 5d8: e8 a3 fe ff ff call 480 <__errno_location@plt>
556 5dd: 8b 10 mov (%eax),%edx
557 5df: 8b 83 e4 ff ff ff mov -0x1c(%ebx),%eax
558 5e5: 8b 00 mov (%eax),%eax
559 5e7: 01 c2 add %eax,%edx
when function add_count compiled to X86_64 64 bits: 当函数add_count编译为X86_64 64位时:
567 789: e8 d2 fe ff ff callq 660 <__errno_location@plt>
568 78e: c7 00 ad de 00 00 movl $0xdead,(%rax)
569 794: e8 c7 fe ff ff callq 660 <__errno_location@plt>
570 799: 8b 10 mov (%rax),%edx
571 79b: 48 8b 05 26 08 20 00 mov 0x200826(%rip),%rax # 200fc8 <_DYNAMIC+0x1c0>
572 7a2: 8b 00 mov (%rax),%eax
573 7a4: 01 c2 add %eax,%edx
mmap FYI mmap FYI
00400000-00401000 r-xp 00000000 08:01 1975032 /home/pli/validation/got.bin
00600000-00601000 r--p 00000000 08:01 1975032 /home/pli/validation/got.bin
00601000-00602000 rw-p 00001000 08:01 1975032 /home/pli/validation/got.bin
7ffff7813000-7ffff79ce000 r-xp 00000000 08:01 5771356 /lib/x86_64-linux-gnu/libc-2.19.so
7ffff79ce000-7ffff7bcd000 ---p 001bb000 08:01 5771356 /lib/x86_64-linux-gnu/libc-2.19.so
7ffff7bcd000-7ffff7bd1000 r--p 001ba000 08:01 5771356 /lib/x86_64-linux-gnu/libc-2.19.so
7ffff7bd1000-7ffff7bd3000 rw-p 001be000 08:01 5771356 /lib/x86_64-linux-gnu/libc-2.19.so
7ffff7bd3000-7ffff7bd8000 rw-p 00000000 00:00 0
7ffff7bd8000-7ffff7bd9000 r-xp 00000000 08:01 5767525 /lib/libextern.so
7ffff7bd9000-7ffff7dd8000 ---p 00001000 08:01 5767525 /lib/libextern.so
7ffff7dd8000-7ffff7dd9000 r--p 00000000 08:01 5767525 /lib/libextern.so
7ffff7dd9000-7ffff7dda000 rw-p 00001000 08:01 5767525 /lib/libextern.so
7ffff7dda000-7ffff7dfd000 r-xp 00000000 08:01 5771353 /lib/x86_64-linux-gnu/ld-2.19.so
7ffff7fed000-7ffff7ff0000 rw-p 00000000 00:00 0
7ffff7ff8000-7ffff7ffa000 rw-p 00000000 00:00 0
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00022000 08:01 5771353 /lib/x86_64-linux-gnu/ld-2.19.so
7ffff7ffd000-7ffff7ffe000 rw-p 00023000 08:01 5771353 /lib/x86_64-linux-gnu/ld-2.19.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
当您切换架构时,这是正常的……只需检查链接脚本以查看内存映射有何不同。
Finally, I found the answer to that tow question and put here for someone may need this. 最后,我找到了这个拖曳问题的答案,并放在这里,因为有人可能需要这个。 1. For fPIC build library, each global variable will be treat as defined external, and there is one copy of this variable in main executable file .bss section. 1.对于fPIC构建库,每个全局变量将被视为外部定义的变量,并且主可执行文件.bss节中有该变量的一个副本。 2. it seems, in IA 32-bits assembly, we cannot get %eip register as base registers. 2.看来,在IA 32位汇编中,我们无法将%eip寄存器作为基址寄存器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.