gcc优化对static函数调用的处理

最近追查一个崩溃问题,反汇编根据调用栈一层层查找,到了某一函数后竞找不到对应代码行,后进入其调用的某一个函数才将其调用顺序串起来。由此做了一个小实验,从汇编层面看看编译器如何处理。

C代码:

#include <stdio.h>

static void myfunc(void)
{
	printf("myfunc in\n");
	printf("myfunc out\n");
}

int main(int argc, char *argv[])
{
	printf("main in\n");
	myfunc();
	printf("main out\n");
	return 0;
}

用 arm-none-linux-gnueabi-gcc main.c 编译,再用arm-none-linux-gnueabi-objdump -d a.out 反汇编输出,从下面汇编片段,可以看出main函数对myfunc的调用: bl    842c <myfunc>

0000842c <myfunc>:
    842c:	e92d4800 	push	{fp, lr}
    8430:	e28db004 	add	fp, sp, #4
    8434:	e59f000c 	ldr	r0, [pc, #12]	; 8448 <myfunc+0x1c>
    8438:	ebffffcd 	bl	8374 <_init+0x44>
    843c:	e59f0008 	ldr	r0, [pc, #8]	; 844c <myfunc+0x20>
    8440:	ebffffcb 	bl	8374 <_init+0x44>
    8444:	e8bd8800 	pop	{fp, pc}
    8448:	0000856c 	.word	0x0000856c
    844c:	00008578 	.word	0x00008578

00008450 <main>:
    8450:	e92d4800 	push	{fp, lr}
    8454:	e28db004 	add	fp, sp, #4
    8458:	e24dd008 	sub	sp, sp, #8
    845c:	e50b0008 	str	r0, [fp, #-8]
    8460:	e50b100c 	str	r1, [fp, #-12]
    8464:	e59f001c 	ldr	r0, [pc, #28]	; 8488 <main+0x38>
    8468:	ebffffc1 	bl	8374 <_init+0x44>
    846c:	ebffffee 	bl	842c <myfunc>
    8470:	e59f0014 	ldr	r0, [pc, #20]	; 848c <main+0x3c>
    8474:	ebffffbe 	bl	8374 <_init+0x44>
    8478:	e3a03000 	mov	r3, #0
    847c:	e1a00003 	mov	r0, r3
    8480:	e24bd004 	sub	sp, fp, #4
    8484:	e8bd8800 	pop	{fp, pc}
    8488:	00008584 	.word	0x00008584
    848c:	0000858c 	.word	0x0000858c

然后再用 arm-none-linux-gnueabi-gcc -O1 main.c 进行1级优化编译, 用arm-none-linux-gnueabi-objdump -d a.out 反汇编输出,从汇编中找不到myfunc,main函数中也没有对其调用, 实际是myfunc较小,将myfunc嵌入到main函数中去了,8438-8444 即myfunc中两个printf调用。

0000842c <main>:
    842c:    e92d4008     push    {r3, lr}
    8430:    e59f0020     ldr    r0, [pc, #32]    ; 8458 <main+0x2c>
    8434:    ebffffce     bl    8374 <_init+0x44>
    8438:    e59f001c     ldr    r0, [pc, #28]    ; 845c <main+0x30>
    843c:    ebffffcc     bl    8374 <_init+0x44>
    8440:    e59f0018     ldr    r0, [pc, #24]    ; 8460 <main+0x34>
    8444:    ebffffca     bl    8374 <_init+0x44>
    8448:    e59f0014     ldr    r0, [pc, #20]    ; 8464 <main+0x38>
    844c:    ebffffc8     bl    8374 <_init+0x44>
    8450:    e3a00000     mov    r0, #0
    8454:    e8bd8008     pop    {r3, pc}
    8458:    00008544     .word    0x00008544
    845c:    0000854c     .word    0x0000854c
    8460:    00008558     .word    0x00008558
    8464:    00008564     .word    0x00008564

----------------------------------------

    8438:    e59f001c     ldr    r0, [pc, #28]    ; 845c <main+0x30>
    843c:    ebffffcc     bl    8374 <_init+0x44>
pc, #28 即845c, 此处存了个内存地址854c, 将(内存指针)854c指向的数据取出来放到 r0, 即"myfunc in\n"的内存首地址,然后调用printf函数。 按照函数调用约定, r0放第一个参数, r1, r2次之,再多的要放在栈上。

printf是C动态库里的函数, 这里没有bl printf之类的语句,实际是bl    8374 <_init+0x44> 这样的做法,然后再跳到真正的打印函数里。 

猜你喜欢

转载自blog.csdn.net/konga/article/details/117875310