祝各位道友念头通达
GitHub Gitee 语雀 打赏

x86汇编指令分析

纯属个人调试过程中的个人理解

GDB调试文档

gdb/vscode 调试指令文档

x86汇编指令分析

对于程序如何在栈中存放: https://www.askpure.com/course_DXMRI553-D81INAOS-06RBPK32-8QGUKX0E.html
结论:
8个通用寄存器:
rax rbx rcx rdx -> 数据寄存器, 都是64bit的, 其实 rax, eax, ax, al/ah 表示的都是同一个寄存器, 指向的位数不同而已
eax ebx ecx edx -> 数据寄存器, eax 32bit, 其中 ax 为 eax 低十六位, al(ah)为ax的低(高十六位)
edi esi (rdi, rsi) -> 变址寄存器
rbp rsp (ebp esp) -> 栈指针寄存器, rsp 一直指向栈的最顶部, rbp 一直指向栈最底部偏移八字节处, 而最底部的八字节存储被调用的 rbp指针
image

环境
x86, 64位机器, linux Centos8, GNU/Linux, gcc 8.5.0, make 4.2.1
栈示例图
image
C代码

#include <stdio.h>
#include <stdlib.h>

void test1(float a1, double a2, short a3, int a4, 
        unsigned int a5, unsigned char a6) {
    int b1 = 0;
    b1 = a1 + a2;
    b1 = a3 + a4 + b1;
    b1 = a5 + a6 + b1;
}
void test(int *ptr, int val, unsigned short val1) {
    ptr[10] = val + val1;
}
void fn0() {
    printf( "first register, last call\n" );
}

void fn1() {
    printf( "next.\n" );
}

int main()
{
    printf("start run \n");
    atexit(fn0);
    atexit(fn1);

    float a1 = 10.1;
    double a2 = 12.54;
    short a3 = 0xDCAB;
    int a4 = 0xABCDABCD;
    unsigned int a5 = 0xADCBADCB;
    unsigned char a6 = 0xDE;
    test1(a1, a2,a3, a4, a5, a6);

    int *null_ptr = NULL;
    unsigned int val = 11;
    unsigned short val1 = 9;
    test(null_ptr, val, val1);            //对空指针指向的内存区域写,会发生段错误

    printf("this is good \n");
    return 0;
}

生成部分汇编代码如下:

  00000000004005d6 <test1>:
  ; rsp 0x7fffffffe238, rbp 0x7fffffffe270 在 rbp没有push之前, rsp和rbp的值是这样的
  4005d6:	55                   	push   %rbp
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe230
  4005d7:	48 89 e5             	mov    %rsp,%rbp
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe230
  4005da:	f3 0f 11 45 ec       	movss  %xmm0,-0x14(%rbp)
  4005df:	f2 0f 11 4d e0       	movsd  %xmm1,-0x20(%rbp)
  4005e4:	89 f8                	mov    %edi,%eax
  4005e6:	89 75 dc             	mov    %esi,-0x24(%rbp)
  4005e9:	89 55 d8             	mov    %edx,-0x28(%rbp)
  4005ec:	89 ca                	mov    %ecx,%edx
  4005ee:	66 89 45 e8          	mov    %ax,-0x18(%rbp) ;ax 值为0xdcab, ax是eax的低十六位, al 是eax的低八位
  4005f2:	89 d0                	mov    %edx,%eax
  4005f4:	88 45 d4             	mov    %al,-0x2c(%rbp) ;al 值为0xab
  4005f7:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%rbp)
  4005fe:	f3 0f 5a 45 ec       	cvtss2sd -0x14(%rbp),%xmm0
  400603:	f2 0f 58 45 e0       	addsd  -0x20(%rbp),%xmm0
  400608:	f2 0f 2c c0          	cvttsd2si %xmm0,%eax
  40060c:	89 45 fc             	mov    %eax,-0x4(%rbp)
  40060f:	0f bf 55 e8          	movswl -0x18(%rbp),%edx
  400613:	8b 45 dc             	mov    -0x24(%rbp),%eax
  400616:	01 d0                	add    %edx,%eax
  400618:	01 45 fc             	add    %eax,-0x4(%rbp)
  40061b:	0f b6 55 d4          	movzbl -0x2c(%rbp),%edx
  40061f:	8b 45 d8             	mov    -0x28(%rbp),%eax
  400622:	01 c2                	add    %eax,%edx
  400624:	8b 45 fc             	mov    -0x4(%rbp),%eax
  400627:	01 d0                	add    %edx,%eax
  400629:	89 45 fc             	mov    %eax,-0x4(%rbp)
  40062c:	90                   	nop
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe230
  40062d:	5d                   	pop    %rbp
  ; rsp 0x7fffffffe238, rbp 0x7fffffffe270
  40062e:	c3                   	retq   

000000000040062f <test>:
  ; rsp 0x7fffffffe238, rbp 0x7fffffffe270
  40062f:	55                   	push   %rbp
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe270
  400630:	48 89 e5             	mov    %rsp,%rbp
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe230
  400633:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)
  400637:	89 75 f4             	mov    %esi,-0xc(%rbp)
  40063a:	89 d0                	mov    %edx,%eax
  40063c:	66 89 45 f0          	mov    %ax,-0x10(%rbp)
  400640:	0f b7 4d f0          	movzwl -0x10(%rbp),%ecx
  400644:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
  400648:	48 83 c0 28          	add    $0x28,%rax
  40064c:	8b 55 f4             	mov    -0xc(%rbp),%edx
  40064f:	01 ca                	add    %ecx,%edx
  400651:	89 10                	mov    %edx,(%rax)
  400653:	90                   	nop
  ; rsp 0x7fffffffe230, rbp 0x7fffffffe270
  400654:	5d                   	pop    %rbp
  ; rsp 0x7fffffffe238, rbp 0x7fffffffe270
  400655:	c3                   	retq


0000000000400678 <main>:
  ; rsp 0x7fffffffe278, rbp 0x400730 <__libc_csu_init>, 进入main函数之前, 在 rbp没有push之前, rsp和rbp的值是这样的
  ; 此时 rsp指向帧帧的栈顶,, rbp 指向 __libc_csu_init 运行的地址, 也就是 __libc_csu_init 所在的栈帧, (个人理解的栈帧和栈顶不是一个概念)
  400678:	55                   	push   %rbp     ;将rbp的寄存器的值推入栈中  
  ; rsp 0x7fffffffe270, rbp 0x400730
  ; 将 rbp入栈, 已知指针为8字节, 所以此时rsp偏移8个字节
  400679:	48 89 e5             	mov    %rsp,%rbp             ; 将rsp
  ; rsp 0x7fffffffe270, rbp 0x7fffffffe270
  ; 然后将rsp的值保存在寄存器rbp中, 此时 rbp作为栈的指针,用于以下数据的入栈出栈处理
  40067c:	48 83 ec 30          	sub    $0x30,%rsp
  ; rsp 0x7fffffffe240, rbp 0x7fffffffe270
  ; 将rsp累加0x30, 开辟空间用于存放变量, 此时rsp指向开辟空间后的位置, 由此可得出结论, rsp是一直指向栈顶的寄存器, rbp的值未变, 指向栈低
  400680:	bf 08 08 40 00       	mov    $0x400808,%edi
  400685:	e8 46 fe ff ff       	callq  4004d0 <puts@plt>
  40068a:	bf 56 06 40 00       	mov    $0x400656,%edi
  40068f:	e8 1c 01 00 00       	callq  4007b0 <atexit>
  ; rip 0x400694
  400694:	bf 67 06 40 00       	mov    $0x400667,%edi
  ; rip 0x400699
  400699:	e8 12 01 00 00       	callq  4007b0 <atexit>
  ;test1 参数初始化传递
  ; rip 0x40069e, 得出结论: rip 总是指向下一条将要执行的指令的汇编地址
  40069e:	f3 0f 10 05 7e 01 00 	movss  0x17e(%rip),%xmm0        # 400824 <__dso_handle+0x44> ;
  4006a5:	00 
  4006a6:	f3 0f 11 45 fc       	movss  %xmm0,-0x4(%rbp) ; float 占用四个字节 0x04
  4006ab:	f2 0f 10 05 75 01 00 	movsd  0x175(%rip),%xmm0        # 400828 <__dso_handle+0x48>
  4006b2:	00
  4006b3:	f2 0f 11 45 f0       	movsd  %xmm0,-0x10(%rbp) ; double占用八个字节,0x10-0x4=0xC=12,这里为什么会多出四个字节
  ; 如果按照正常来算 -0xC(%rbp), 0x7fffffffe264, 也能被4 除尽,应该也不是需要地址对齐, 暂时没搞明白
  ; GUN为mov添加了一个维度: movl 32位字长度, movw 16位字长度, movb 8位字长度
  4006b8:	66 c7 45 ee ab dc    	movw   $0xdcab,-0x12(%rbp) ;short 占用2字节, 0x12 - 0x10
  4006be:	c7 45 e8 cd ab cd ab 	movl   $0xabcdabcd,-0x18(%rbp) ;int 占用四字节, 这里是占用了0x18-0x12=6, 又多了两个字节
  4006c5:	c7 45 e4 cb ad cb ad 	movl   $0xadcbadcb,-0x1c(%rbp) ;无符号int战四字节, 0x1c-0x18=4,是四字节
  4006cc:	c6 45 e3 de          	movb   $0xde,-0x1d(%rbp) ;无符号char, 占一字节

  4006d0:	0f b6 4d e3          	movzbl -0x1d(%rbp),%ecx ;ecx值为0xde
  4006d4:	0f bf 45 ee          	movswl -0x12(%rbp),%eax ;eax值为0xffffdcab, 在寄存器中存储实则为4字节
  4006d8:	8b 55 e4             	mov    -0x1c(%rbp),%edx ;edx  0xadcbadcb
  4006db:	8b 75 e8             	mov    -0x18(%rbp),%esi ;0xabcdabcd
  4006de:	f2 0f 10 4d f0       	movsd  -0x10(%rbp),%xmm1;xmm1 和xmm0 存储的是浮点型
  4006e3:	f3 0f 10 45 fc       	movss  -0x4(%rbp),%xmm0
  4006e8:	89 c7                	mov    %eax,%edi
  ; rsp 0x7fffffffe240, rbp 0x7fffffffe270
  4006ea:	e8 e7 fe ff ff       	callq  4005d6 <test1>
  ; rsp 0x7fffffffe240, rbp 0x7fffffffe270
  ;test 参数初始化传递
  4006ef:	48 c7 45 d8 00 00 00 	movq   $0x0,-0x28(%rbp)
  4006f6:	00 
  4006f7:	c7 45 d4 0b 00 00 00 	movl   $0xb,-0x2c(%rbp)
  4006fe:	66 c7 45 d2 09 00    	movw   $0x9,-0x2e(%rbp)
  400704:	0f b7 55 d2          	movzwl -0x2e(%rbp),%edx
  400708:	8b 4d d4             	mov    -0x2c(%rbp),%ecx
  40070b:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
  40070f:	89 ce                	mov    %ecx,%esi
  400711:	48 89 c7             	mov    %rax,%rdi
  400714:	e8 16 ff ff ff       	callq  40062f <test>
  400706:	bf 03 08 40 00       	mov    $0x400803,%edi
  40070b:	e8 c0 fd ff ff       	callq  4004d0 <puts@plt>
  400710:	b8 00 00 00 00       	mov    $0x0,%eax
  ; rsp 0x7fffffffe240, rbp 0x7fffffffe270
  400715:	c9                   	leaveq 
  ; rsp 0x7fffffffe238, rbp 0x400730 <__libc_csu_init>
  400716:	c3                   	retq   
  400717:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
  40071e:	00 00

  ;8个通用寄存器:
  ; eax ebx ecx edx -> 数据寄存器, 存储运算过程中数据的存放, 其中 ax 为 eax 低十六位, al(ah)为ax的低(高十六位)
  ; edi esi -> 变址寄存器 
  ; rbp rsp (ebp esp) -> 栈指针寄存器, rsp 一直指向栈的最顶部, rbp 一直指向

上述汇编代码中还有存在两个疑问:

  1. 0x4006be 行中, 一个double占八个字节, 实际rbp偏移多出四个字节
    0x4006b3 行中, 一个int 占四个字节, 实际rbp偏移多出两个字节
  2. 0x4006ea 行中, 在main中方法跳转到test1的时候, rsp 直接从 0x7fffffffe240 跳转 0x7fffffffe238, 为什么会少了两个字节
  3. 0x40067c 行中, 在main中开辟了 0x30 的空间, 但是在 test1 中也定义了变量, 为什么没有开辟空间, 同样的, 在main函数中如果再加变量, 0x30 还会增加, 但是在test中加多少变量, main 中开辟的空间没有变化, test1 中也没有开辟空间

linux c 可执行文件如何被系统掉用

https://zhuanlan.zhihu.com/p/52054044

同样的, 源码如三, 汇编之后的代码如下, 点击查看:
a.out:     文件格式 elf64-x86-64


Disassembly of section .init:

0000000000400428 <_init>:
  400428:	f3 0f 1e fa          	endbr64 
  40042c:	48 83 ec 08          	sub    $0x8,%rsp
  400430:	48 8b 05 b9 0b 20 00 	mov    0x200bb9(%rip),%rax        # 600ff0 <__gmon_start__>
  400437:	48 85 c0             	test   %rax,%rax
  40043a:	74 02                	je     40043e <_init+0x16>
  40043c:	ff d0                	callq  *%rax
  40043e:	48 83 c4 08          	add    $0x8,%rsp
  400442:	c3                   	retq   

Disassembly of section .text:

0000000000400450 <_start>:
  400450:	f3 0f 1e fa          	endbr64 
  400454:	31 ed                	xor    %ebp,%ebp
  400456:	49 89 d1             	mov    %rdx,%r9
  400459:	5e                   	pop    %rsi
  40045a:	48 89 e2             	mov    %rsp,%rdx
  40045d:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
  400461:	50                   	push   %rax
  400462:	54                   	push   %rsp
  400463:	49 c7 c0 f0 05 40 00 	mov    $0x4005f0,%r8
  40046a:	48 c7 c1 80 05 40 00 	mov    $0x400580,%rcx
  400471:	48 c7 c7 51 05 40 00 	mov    $0x400551,%rdi
  400478:	ff 15 6a 0b 20 00    	callq  *0x200b6a(%rip)        # 600fe8 <__libc_start_main@GLIBC_2.2.5>
  40047e:	f4                   	hlt    

000000000040047f <.annobin_init.c>:
  40047f:	90                   	nop

0000000000400480 <_dl_relocate_static_pie>:
  400480:	f3 0f 1e fa          	endbr64 
  400484:	c3                   	retq   

0000000000400485 <.annobin__dl_relocate_static_pie.end>:
  400485:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  40048c:	00 00 00 
  40048f:	90                   	nop

0000000000400490 <deregister_tm_clones>:
  400490:	48 8d 3d 89 0b 20 00 	lea    0x200b89(%rip),%rdi        # 601020 <__TMC_END__>
  400497:	48 8d 05 82 0b 20 00 	lea    0x200b82(%rip),%rax        # 601020 <__TMC_END__>
  40049e:	48 39 f8             	cmp    %rdi,%rax
  4004a1:	74 15                	je     4004b8 <deregister_tm_clones+0x28>
  4004a3:	48 8b 05 36 0b 20 00 	mov    0x200b36(%rip),%rax        # 600fe0 <_ITM_deregisterTMCloneTable>
  4004aa:	48 85 c0             	test   %rax,%rax
  4004ad:	74 09                	je     4004b8 <deregister_tm_clones+0x28>
  4004af:	ff e0                	jmpq   *%rax
  4004b1:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)
  4004b8:	c3                   	retq   
  4004b9:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

00000000004004c0 <register_tm_clones>:
  4004c0:	48 8d 3d 59 0b 20 00 	lea    0x200b59(%rip),%rdi        # 601020 <__TMC_END__>
  4004c7:	48 8d 35 52 0b 20 00 	lea    0x200b52(%rip),%rsi        # 601020 <__TMC_END__>
  4004ce:	48 29 fe             	sub    %rdi,%rsi
  4004d1:	48 c1 fe 03          	sar    $0x3,%rsi
  4004d5:	48 89 f0             	mov    %rsi,%rax
  4004d8:	48 c1 e8 3f          	shr    $0x3f,%rax
  4004dc:	48 01 c6             	add    %rax,%rsi
  4004df:	48 d1 fe             	sar    %rsi
  4004e2:	74 14                	je     4004f8 <register_tm_clones+0x38>
  4004e4:	48 8b 05 0d 0b 20 00 	mov    0x200b0d(%rip),%rax        # 600ff8 <_ITM_registerTMCloneTable>
  4004eb:	48 85 c0             	test   %rax,%rax
  4004ee:	74 08                	je     4004f8 <register_tm_clones+0x38>
  4004f0:	ff e0                	jmpq   *%rax
  4004f2:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)
  4004f8:	c3                   	retq   
  4004f9:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

0000000000400500 <__do_global_dtors_aux>:
  400500:	f3 0f 1e fa          	endbr64 
  400504:	80 3d 11 0b 20 00 00 	cmpb   $0x0,0x200b11(%rip)        # 60101c <_edata>
  40050b:	75 13                	jne    400520 <__do_global_dtors_aux+0x20>
  40050d:	55                   	push   %rbp
  40050e:	48 89 e5             	mov    %rsp,%rbp
  400511:	e8 7a ff ff ff       	callq  400490 <deregister_tm_clones>
  400516:	c6 05 ff 0a 20 00 01 	movb   $0x1,0x200aff(%rip)        # 60101c <_edata>
  40051d:	5d                   	pop    %rbp
  40051e:	c3                   	retq   
  40051f:	90                   	nop
  400520:	c3                   	retq   
  400521:	66 66 2e 0f 1f 84 00 	data16 nopw %cs:0x0(%rax,%rax,1)
  400528:	00 00 00 00 
  40052c:	0f 1f 40 00          	nopl   0x0(%rax)

0000000000400530 <frame_dummy>:
  400530:	f3 0f 1e fa          	endbr64 
  400534:	eb 8a                	jmp    4004c0 <register_tm_clones>

0000000000400536 <test>:
  400536:	55                   	push   %rbp
  400537:	48 89 e5             	mov    %rsp,%rbp
  40053a:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)
  40053e:	89 75 f4             	mov    %esi,-0xc(%rbp)
  400541:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
  400545:	48 8d 50 28          	lea    0x28(%rax),%rdx
  400549:	8b 45 f4             	mov    -0xc(%rbp),%eax
  40054c:	89 02                	mov    %eax,(%rdx)
  40054e:	90                   	nop
  40054f:	5d                   	pop    %rbp
  400550:	c3                   	retq   

0000000000400551 <main>:
  400551:	55                   	push   %rbp
  400552:	48 89 e5             	mov    %rsp,%rbp
  400555:	48 83 ec 10          	sub    $0x10,%rsp
  400559:	c7 45 fc 0b 00 00 00 	movl   $0xb,-0x4(%rbp)
  400560:	48 c7 45 f0 00 00 00 	movq   $0x0,-0x10(%rbp)
  400567:	00 
  400568:	8b 55 fc             	mov    -0x4(%rbp),%edx
  40056b:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
  40056f:	89 d6                	mov    %edx,%esi
  400571:	48 89 c7             	mov    %rax,%rdi
  400574:	e8 bd ff ff ff       	callq  400536 <test>
  400579:	b8 00 00 00 00       	mov    $0x0,%eax
  40057e:	c9                   	leaveq 
  40057f:	c3                   	retq   

0000000000400580 <__libc_csu_init>:
  400580:	f3 0f 1e fa          	endbr64 
  400584:	41 57                	push   %r15
  400586:	49 89 d7             	mov    %rdx,%r15
  400589:	41 56                	push   %r14
  40058b:	49 89 f6             	mov    %rsi,%r14
  40058e:	41 55                	push   %r13
  400590:	41 89 fd             	mov    %edi,%r13d
  400593:	41 54                	push   %r12
  400595:	4c 8d 25 a4 08 20 00 	lea    0x2008a4(%rip),%r12        # 600e40 <__frame_dummy_init_array_entry>
  40059c:	55                   	push   %rbp
  40059d:	48 8d 2d a4 08 20 00 	lea    0x2008a4(%rip),%rbp        # 600e48 <__init_array_end>
  4005a4:	53                   	push   %rbx
  4005a5:	4c 29 e5             	sub    %r12,%rbp
  4005a8:	48 83 ec 08          	sub    $0x8,%rsp
  4005ac:	e8 77 fe ff ff       	callq  400428 <_init>
  4005b1:	48 c1 fd 03          	sar    $0x3,%rbp
  4005b5:	74 1f                	je     4005d6 <__libc_csu_init+0x56>
  4005b7:	31 db                	xor    %ebx,%ebx
  4005b9:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)
  4005c0:	4c 89 fa             	mov    %r15,%rdx
  4005c3:	4c 89 f6             	mov    %r14,%rsi
  4005c6:	44 89 ef             	mov    %r13d,%edi
  4005c9:	41 ff 14 dc          	callq  *(%r12,%rbx,8)
  4005cd:	48 83 c3 01          	add    $0x1,%rbx
  4005d1:	48 39 dd             	cmp    %rbx,%rbp
  4005d4:	75 ea                	jne    4005c0 <__libc_csu_init+0x40>
  4005d6:	48 83 c4 08          	add    $0x8,%rsp
  4005da:	5b                   	pop    %rbx
  4005db:	5d                   	pop    %rbp
  4005dc:	41 5c                	pop    %r12
  4005de:	41 5d                	pop    %r13
  4005e0:	41 5e                	pop    %r14
  4005e2:	41 5f                	pop    %r15
  4005e4:	c3                   	retq   

00000000004005e5 <.annobin___libc_csu_fini.start>:
  4005e5:	66 66 2e 0f 1f 84 00 	data16 nopw %cs:0x0(%rax,%rax,1)
  4005ec:	00 00 00 00 

00000000004005f0 <__libc_csu_fini>:
  4005f0:	f3 0f 1e fa          	endbr64 
  4005f4:	c3                   	retq   

Disassembly of section .fini:

00000000004005f8 <_fini>:
  4005f8:	f3 0f 1e fa          	endbr64 
  4005fc:	48 83 ec 08          	sub    $0x8,%rsp
  400600:	48 83 c4 08          	add    $0x8,%rsp
  400604:	c3                   	retq   
使用 nm 和 ldd 查看 a.out 中链接的库和所有方法, 点击查看
[root@cen8 han]# nm a.out
0000000000400485 t .annobin__dl_relocate_static_pie.end
...
00000000004005f8 T _fini
0000000000400530 t frame_dummy
0000000000600e40 t __frame_dummy_init_array_entry
0000000000400734 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400618 r __GNU_EH_FRAME_HDR
0000000000400428 T _init
0000000000600e48 t __init_array_end
0000000000600e40 t __init_array_start
0000000000400608 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
00000000004005f0 T __libc_csu_fini
0000000000400580 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400551 T main
00000000004004c0 t register_tm_clones
0000000000400450 T _start
0000000000400536 T test
0000000000601020 D __TMC_END__
[root@cen8 han]# ldd ./a.out
        linux-vdso.so.1 (0x00007ffc773f9000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fb046233000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb0465f8000)

说明

  1. /lib64/ld-linux-x86-64.so.2: glibc 是Linux下的GUN C函数库,可单独运行, 负责动态加载, 通过读取可执行文件的头部信息来确定那些库文件是必须的, 以及哪些需要加载。加载完成之后, 它会通过修正执行文件里相关的地址指针来和加载的库文件完成动态链接, 此时程序就可以运行了
    glibc是linux下面c标准库的实现,即GNU C Library。glibc本身是GNU旗下的C标准库,后来逐渐成为了Linux的标准c(新标准C99),而Linux下原来的标准c库Linux libc逐渐不再被维护。
    glibc逐渐成linux标准C的原因: 归于GUN的发展壮大, GUN是一种操作系统 GUN/Linux: LinusTorvalds在1991年开发出与Unix兼容的内核Linux, GUN将Linux内核和GUN系统结合产生了一个非常完成的自由软件操作系统, 称之为 GUN/Linux, Linux开源内核代码,其实就是GUN/Linux操作系统
  2. libc.so.6 => /lib64/libc.so.6: glibc链接库, 提供了很多库函数. string, signal,io等基本功能
  3. linux-vdso.so.1: 内核自动映射到每个进程地址空间的文件。它的工作是找到并定位进程所需的其他共享库。
  4. 从上述汇编中可以看出,C代码编译成二进制文件,会分为多个区, 这里只显示: .init, .text, .fini
  5. 程序执行, _start -> __libc_start_main -> main , 这块可以用 gdb starti 指令调试查看.
    __libc_start_main 还调用了__libc_csu_init函数, __libc_csu_init 会调用 _init 函数

当程序开始执行的时候, shell 或 GUI会调用 execve, 使用 man execve, 可以查看execve手册,
__libc_start_main 函数原型

int __libc_start_main(  int (*main) (int, char * *, char * *),
         int argc, char * * ubp_av,
         void (*init) (void),
         void (*fini) (void),
         void (*rtld_fini) (void),
         void (* stack_end));

作用:  
   处理关于setuid、setgid程序的安全问题
   启动线程
   注册用户程序的fini和rtld_fini参数,然后被at_exit调用,从而完成用户程序和加载器的负责清理工作的函数
   调用其init参数
   调用main函数,并把argc和argv参数、环境变量传递给它
   调用exit函数,并将main函数的返回值传递给它
posted @ 2022-12-01 11:00  韩若明瞳  阅读(788)  评论(0编辑  收藏  举报