KEEP

KEEP(expr ...)

e.g. 三个源文件 DemoA.c,DemoB.c 和 DemoC.c,其中 DemoA.c 引用 DemoA.c 和 DemoB.c 里面的函数,使用 GCC 生成独立的目标文件 DemoA.o,DemoB.o 和 DemoC.o。 ld 使用链接脚本 Demo.lds, 并且在 Demo.lds 里面通过 KEEP 关键字保存 .comment section,ld 命令行中添加 –gc-sections 选项:

DemoA.c

extern void print();
extern void exit();

void nomain()
{
    print();
    exit();
}

DemoB.c

char *str = "Hello World\n";

void print()
{
    __asm__ ("movl $13, %%edx\n\t"
             "movl %0, %%ecx\n\t"
             "movl $0, %%ebx\n\t"
             "movl $4, %%eax\n\r"
             "int $0x80\n\t"
             :: "r" (str) : "edx", "ecx", "ebx");
}

DemoC.c

void exit()
{
    __asm__ ("movl $42, %ebx\n\t"
             "movl $1, %eax\n\t"
             "int $0x80\n\t");
}

Demo.lds 不使用 KEEP 关键字

ENTRY(nomain)

SECTIONS
{
    . = 0x08048000 + SIZEOF_HEADERS;

    DemoText  { *(.text) *(.data) *(.rodata) }

    /DISCARD/ : { *(.comment) }
}

DemoC.lds 中使用 KEEP 关键字

ENTRY(nomain)

SECTIONS
{
    . = 0x08048000 + SIZEOF_HEADERS;

    DemoText  { *(.text) *(.data) *(.rodata) }

    DemoComment  { KEEP(*(.eh_frame)) }

    /DISCARD/ : { *(.comment) }

}

使用如下命令进行编译和链接:

gcc DemoA.c -c
gcc DemoB.c -c
gcc DemoC.c -c -fno-builtin
ld -static -T Demo.lds DemoA.o DemoB.o DemoC.c -o a.out --gc-sections -M

LD

如上图数据,通过使用 Demo.lds 脚本进行链接,并且 ld 使用了 –gc-sections 命令 之后,生成的 a.out 可执行文件中并未包含 .eh_frame section。然后,在链接脚本 DemoC.lds 中使用 KEEP 关键字将 .eh_frame 作为保留 section,运行结果如下:

LD

通过上面的数据可知,输出文件 a.out 的 Demoelf section 包含了所有 .eh_frame sections。

通过实践验证之后, KEEP 关键可以保留 section 到输出文件中。


附录

BiscuitOS Home

BiscuitOS Driver

BiscuitOS Kernel Build

Linux Kernel

Bootlin: Elixir Cross Referencer

赞赏一下吧 🙂

MMU