__libc_start_main @ plt如何工作? [英] how __libc_start_main@plt works?
问题描述
要研究目标文件如何在linux中加载和运行,我制作了最简单的c代码,文件名为simple.c.
To study how the object file loaded and run in linux, I made the simplest c code, file name simple.c.
int main(){}
接下来,我制作目标文件并将目标文件另存为文本文件.
Next, I make object file and save object file as text file.
$gcc ./simple.c
$objdump -xD ./a.out > simple.text
从许多互联网文章中,我可以发现gcc动态加载了诸如_start,_init,__ libc_start_main @ plt等启动函数.因此,在 http://dbp-consulting.com/的帮助下,我开始阅读我的汇编代码. tutorials/debugging/linuxProgramStartup.html .
From many internet articles, I could catch that gcc dynamically load initiating functions like _start, _init, __libc_start_main@plt, and so on. So I started to read my assembly code, helped by http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html .
这是汇编代码的一部分.
Here is the some part of assembly code.
080482e0 <__libc_start_main@plt>:
80482e0: ff 25 10 a0 04 08 jmp *0x804a010
80482e6: 68 08 00 00 00 push $0x8
80482eb: e9 d0 ff ff ff jmp 80482c0 <_init+0x2c>
Disassembly of section .text:
080482f0 <_start>:
80482f0: 31 ed xor %ebp,%ebp
80482f2: 5e pop %esi
80482f3: 89 e1 mov %esp,%ecx
80482f5: 83 e4 f0 and $0xfffffff0,%esp
80482f8: 50 push %eax
80482f9: 54 push %esp
80482fa: 52 push %edx
80482fb: 68 70 84 04 08 push $0x8048470
8048300: 68 00 84 04 08 push $0x8048400
8048305: 51 push %ecx
8048306: 56 push %esi
8048307: 68 ed 83 04 08 push $0x80483ed
804830c: e8 cf ff ff ff call 80482e0 <__libc_start_main@plt>
8048311: f4 hlt
8048312: 66 90 xchg %ax,%ax
8048314: 66 90 xchg %ax,%ax
8048316: 66 90 xchg %ax,%ax
8048318: 66 90 xchg %ax,%ax
804831a: 66 90 xchg %ax,%ax
804831c: 66 90 xchg %ax,%ax
804831e: 66 90 xchg %ax,%ax
080483ed <main>:
80483ed: 55 push %ebp
80483ee: 89 e5 mov %esp,%ebp
80483f0: b8 00 00 00 00 mov $0x0,%eax
80483f5: 5d pop %ebp
80483f6: c3 ret
80483f7: 66 90 xchg %ax,%ax
80483f9: 66 90 xchg %ax,%ax
80483fb: 66 90 xchg %ax,%ax
80483fd: 66 90 xchg %ax,%ax
80483ff: 90 nop
...
Disassembly of section .got:
08049ffc <.got>:
8049ffc: 00 00 add %al,(%eax)
...
Disassembly of section .got.plt:
0804a000 <_GLOBAL_OFFSET_TABLE_>:
804a000: 14 9f adc $0x9f,%al
804a002: 04 08 add $0x8,%al
...
804a00c: d6 (bad)
804a00d: 82 (bad)
804a00e: 04 08 add $0x8,%al
804a010: e6 82 out %al,$0x82
804a012: 04 08 add $0x8,%al
我的问题是
在0x804830c中,称为0x80482e0(我已经理解了前面的指令.).
In 0x804830c, 0x80482e0 is called (I've already apprehended the previous instructions.).
在0x80482e0中,进程跳至0x804a010.
In 0x80482e0, the process jump to 0x804a010.
在0x804a010中,指令为< out%al,$ 0x82>
In 0x804a010, the instruction is < out %al,$0x82 >
...等等.刚出去? %al中有什么,0x82在哪里?我陷入了这一行.
...wait. just out? What was in the %al and where is 0x82?? I got stuck in this line.
请帮助....
* p.s.我是Linux和操作系统的初学者.我正在按学校班级学习操作系统概念,但仍然找不到如何学习正确的Linux汇编语言的方法.我已经下载了英特尔处理器手册,但是它太大了,无法阅读.谁能告诉我关于我的好材料?谢谢.
*p.s. I'm beginner to linux and operating system. I'm studying operating system concepts by school class, but still can not find how to study proper linux assembly language. I've already downloaded intel processor manual but it is too huge to read. Can anyone inform me good material for me? Thanks.
推荐答案
80482e0: ff 25 10 a0 04 08 jmp *0x804a010
这意味着检索存储在0x804a010的4字节地址并跳转到该地址."
This means "retrieve the 4-byte address stored at 0x804a010 and jump to it."
804a010: e6 82 out %al,$0x82
804a012: 04 08 add $0x8,%al
这4个字节将被视为地址0x80482e6,而不是指令.
Those 4 bytes will be treated as an address, 0x80482e6, not as instructions.
80482e0: ff 25 10 a0 04 08 jmp *0x804a010
80482e6: 68 08 00 00 00 push $0x8
80482eb: e9 d0 ff ff ff jmp 80482c0 <_init+0x2c>
因此,我们刚刚执行了一条指令,将我们恰好向前移动了一条指令.此时,您可能想知道是否有充分的理由.
So we've just executed an instruction that has moved us exactly one instruction forward. At this point, you're probably wondering if there's a good reason for this.
有.这是典型的PLT/GOT实现.包括图表在内的更多详细信息,请参见
There is. This is a typical PLT/GOT implementation. Much more detail, including a diagram, is at Position Independent Code in shared libraries: The Procedure Linkage Table.
__libc_start_main
的实际代码在共享库glibc
中.编译器和编译时链接程序不知道代码在运行时的位置,因此它们在您的编译程序中放置了一个简短的__libc_start_main
函数,该函数仅包含三个指令:
The real code for __libc_start_main
is in a shared library, glibc
. The compiler and compile-time linker don't know where the code will be at run-time, so they place in your compiled program a short __libc_start_main
function which contains just three instructions:
- 跳转到GOT中第4个(或第5个,取决于您是从0还是1开始计数)指定的位置
- 将$ 8压入堆栈
- 跳转到解析器例程
第一次调用__libc_start_main
时,解析器代码将运行.它将在共享库中找到__libc_start_main
的实际位置,并将GOT的第4个条目修补为该地址.如果您的程序再次调用__libc_start_main
,则jmp *0x804a010
指令会将程序直接带到共享库中的代码.
The first time you call __libc_start_main
, the resolver code will run. It will find the actual location of __libc_start_main
in a shared library and will patch the 4th entry of the GOT to be that address. If your program calls __libc_start_main
again, the jmp *0x804a010
instruction will take the program directly to the code in the shared library.
有人可以告诉我对我有用的材料吗?
Can anyone inform me good material for me?
Wikibooks上的 x86汇编书可能是一个起点.
The x86 Assembly book at Wikibooks might be one place to start.
这篇关于__libc_start_main @ plt如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!