最近我看了一下plt和如何實現,並編寫了一段如下所示的用於跟蹤的示例代碼。而且我看到了一些讓我困惑的事情。共享圖庫中的全局變量在32位和64位二進制中以及它的位置有不同的訪問方式?
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);
}
並編譯如下:
gcc -shared -fpic extern.c -o extern.so
sudo cp extern.so /lib/libextern.so
gcc -g got.c -o got.bin -lextern
問題1:在libextern計數 爲什麼全局變量的地址。那麼是0x601048?
問題2: 用於外部符號,使用.plt和.got.plt進行延遲綁定,但對於像count這樣的全局變量,爲什麼32位使用get_pc_thunk來引用.got,而64位只是0xXXX(% rip)來處理.got?或者32位可以使用這種rip + offset方式來處理libextern.so的.got?
在此先感謝!
當-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 <[email protected]>
554 5d2: c7 00 ad de 00 00 movl $0xdead,(%eax)
555 5d8: e8 a3 fe ff ff call 480 <[email protected]>
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
當功能ADD_COUNT編譯爲X86_64 64位:
567 789: e8 d2 fe ff ff callq 660 <[email protected]>
568 78e: c7 00 ad de 00 00 movl $0xdead,(%rax)
569 794: e8 c7 fe ff ff callq 660 <[email protected]>
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
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]
謝謝,這意味着我可以使用64位二進制鏈接腳本的方式在32位二進制,對不對? –
可能不是......這就像是說:那麼我可以在我的IPv4平臺中使用IPv6地址的整個空間。只是他們不適合。 64允許64位內存(超過32位的crunchillon字節允許)認爲虛擬地址的空間是64位可尋址的,而舊的只有32位。對於你現在32位的每個地址,現在你有32位地址的全部範圍來傳播一個進程的虛擬內存。 –
得到了,它幾乎取決於,謝謝,:-) –