readelf 如何计算函数大小
How are function sizes calculated by readelf
我想了解 readelf 实用程序如何计算函数大小。我写了一个简单的程序
#include <stdio.h>
int main() {
printf("Test!\n");
}
现在检查函数大小我使用了这个(可以吗?):
readelf -sw a.out|sort -n -k 3,3|grep FUNC
产生了:
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
29: 0000000000400470 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
30: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
31: 00000000004004e0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
34: 0000000000400500 0 FUNC LOCAL DEFAULT 13 frame_dummy
48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
50: 00000000004005b4 0 FUNC GLOBAL DEFAULT 14 _fini
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
58: 0000000000400440 0 FUNC GLOBAL DEFAULT 13 _start
64: 00000000004003e0 0 FUNC GLOBAL DEFAULT 11 _init
45: 00000000004005b0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
60: 000000000040052d 16 FUNC GLOBAL DEFAULT 13 main
56: 0000000000400540 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
现在,如果我检查主函数的大小,它会显示 16。它是如何得出的?那是筹码量吗?
编译器使用gcc版本4.8.5 (Ubuntu 4.8.5-2ubuntu1~14.04.1)
GNU readelf(Ubuntu 的 GNU Binutils)2.24
ELF 符号有一个属性 st_size
指定它们的大小(参见 <elf.h>
):
typedef struct
{
...
Elf32_Word st_size; /* Symbol size */
...
} Elf32_Sym;
此属性由生成二进制文件的工具链生成;例如查看C编译器生成的汇编代码时:
gcc -c -S test.c
cat test.s
你会看到类似
的东西
.globl main
.type main, @function
main:
...
.LFE0:
.size main, .-main
其中 .size
是一个特殊的伪操作。
更新:
.size
是代码的大小
这里,.size
被赋值为. - main
的结果,其中“.
”是实际地址,main
是main()
开始的地址.
在 ensc 提供的 'cat test.s' 输出中,“秘诀”是 'main:' 和 '.LFE0:' 之间的“...”;这些是编译器生成的汇编指令,用于实现对 printf() 的调用。每条汇编指令对应的机器码占用一定的字节数; “。”每条指令使用的字节数递增,所以在main的最后,“.-main”是main()的机器指令占用的总字节数。
编译器决定执行 printf() 调用所需的汇编指令序列,并且因目标和优化级别而异。在您的情况下,您的编译器生成的机器代码占用 16 个字节。 '.size 主要,. - main' 导致汇编程序为 main() 创建 ELF 符号,其 st_size 字段设置为 16。
readelf 读取了 main 的 ELF 符号,看到它的 st_size 字段是 16,并忠实地报告 16 作为 main() 的大小。 readelf 不会 'calculate' 函数的大小——它只是报告函数的 ELF 符号的 st_size 字段。计算由汇编程序完成,当它解释 '.size main, . - 主要指令。
我想了解 readelf 实用程序如何计算函数大小。我写了一个简单的程序
#include <stdio.h>
int main() {
printf("Test!\n");
}
现在检查函数大小我使用了这个(可以吗?):
readelf -sw a.out|sort -n -k 3,3|grep FUNC
产生了:
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
29: 0000000000400470 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
30: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
31: 00000000004004e0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
34: 0000000000400500 0 FUNC LOCAL DEFAULT 13 frame_dummy
48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
50: 00000000004005b4 0 FUNC GLOBAL DEFAULT 14 _fini
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
58: 0000000000400440 0 FUNC GLOBAL DEFAULT 13 _start
64: 00000000004003e0 0 FUNC GLOBAL DEFAULT 11 _init
45: 00000000004005b0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
60: 000000000040052d 16 FUNC GLOBAL DEFAULT 13 main
56: 0000000000400540 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
现在,如果我检查主函数的大小,它会显示 16。它是如何得出的?那是筹码量吗?
编译器使用gcc版本4.8.5 (Ubuntu 4.8.5-2ubuntu1~14.04.1)
GNU readelf(Ubuntu 的 GNU Binutils)2.24
ELF 符号有一个属性 st_size
指定它们的大小(参见 <elf.h>
):
typedef struct
{
...
Elf32_Word st_size; /* Symbol size */
...
} Elf32_Sym;
此属性由生成二进制文件的工具链生成;例如查看C编译器生成的汇编代码时:
gcc -c -S test.c
cat test.s
你会看到类似
的东西 .globl main
.type main, @function
main:
...
.LFE0:
.size main, .-main
其中 .size
是一个特殊的伪操作。
更新:
.size
是代码的大小
这里,.size
被赋值为. - main
的结果,其中“.
”是实际地址,main
是main()
开始的地址.
在 ensc 提供的 'cat test.s' 输出中,“秘诀”是 'main:' 和 '.LFE0:' 之间的“...”;这些是编译器生成的汇编指令,用于实现对 printf() 的调用。每条汇编指令对应的机器码占用一定的字节数; “。”每条指令使用的字节数递增,所以在main的最后,“.-main”是main()的机器指令占用的总字节数。
编译器决定执行 printf() 调用所需的汇编指令序列,并且因目标和优化级别而异。在您的情况下,您的编译器生成的机器代码占用 16 个字节。 '.size 主要,. - main' 导致汇编程序为 main() 创建 ELF 符号,其 st_size 字段设置为 16。
readelf 读取了 main 的 ELF 符号,看到它的 st_size 字段是 16,并忠实地报告 16 作为 main() 的大小。 readelf 不会 'calculate' 函数的大小——它只是报告函数的 ELF 符号的 st_size 字段。计算由汇编程序完成,当它解释 '.size main, . - 主要指令。