[英]Where is source code for "cold" functions located in glibc?
I have a hello world program in C:我在 C 中有一个 hello world 程序:
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
Compile it gcc -static hello.c -o hello
编译
gcc -static hello.c -o hello
In readelf -a --wide hello
I found some functions with cold postfix在
readelf -a --wide hello
我发现了一些带有冷后缀的函数
__assert_fail_base.cold
_nl_load_domain.cold
_IO_new_fclose.cold
_IO_fflush.cold
_IO_puts.cold
_IO_wfile_underflow.cold
_IO_new_file_underflow.cold
_IO_fputs.cold
_IO_fwrite.cold
_IO_getdelim.cold
__printf_fp_l.cold
__printf_fphex.cold
read_encoded_value_with_base.cold
base_of_encoded_value.cold
execute_cfa_program.cold
uw_frame_state_for.cold
uw_install_context_1.cold
execute_stack_op.cold
uw_update_context_1.cold
uw_init_context_1.cold
uw_update_context.cold
_Unwind_RaiseException_Phase2.cold
_Unwind_GetGR.cold
_Unwind_SetGR.cold
_Unwind_Resume.cold
_Unwind_Resume_or_Rethrow.cold
size_of_encoded_value.cold
base_from_object.cold
base_from_cb_data.cold
read_encoded_value_with_base.cold
_Unwind_IteratePhdrCallback.cold
search_object.cold
base_of_encoded_value.cold
read_encoded_value_with_base.cold
The cold attribute on functions is used to inform the compiler that the function is unlikely to be executed.
函数的冷属性用于通知编译器该函数不太可能被执行。 The function is optimized for size rather than speed and on many targets it is placed into a special subsection of the text section so all cold functions appear close together, improving code locality of non-cold parts of program.
该函数针对大小而不是速度进行了优化,并且在许多目标上,它被放置在文本部分的特殊子部分中,因此所有冷函数看起来很接近,从而提高了程序非冷部分的代码局部性。 The paths leading to calls of cold functions within code are marked as unlikely by the branch prediction mechanism.
分支预测机制将导致代码中冷函数调用的路径标记为不太可能。 It is thus useful to mark functions used to handle unlikely conditions, such as perror, as cold to improve optimization of hot functions that do call marked functions in rare occasions.
因此,将用于处理不太可能的情况(例如 perror)的函数标记为冷函数是有用的,以改进在极少数情况下调用标记函数的热函数的优化。
When profile feedback is available, via -fprofile-use, cold functions are automatically detected and this attribute is ignored.
当配置文件反馈可用时,通过 -fprofile-use 会自动检测冷功能并忽略此属性。
According that I download glibc and switch to commit 160f6c36a374841ee6e2bf2ee0ba05b70634978e
which points to my version git rev-list -n 1 $(git tag | grep 2.31-0ubuntu9.7)
, but after all of this actions I cannot find any functions from above marked with the cold atribute.根据我下载glibc 并切换到提交
160f6c36a374841ee6e2bf2ee0ba05b70634978e
,它指向我的版本git rev-list -n 1 $(git tag | grep 2.31-0ubuntu9.7)
,但是在所有这些操作之后我找不到上面标有的任何函数冷属性。
I know that glibc generates some of the syscalls, but I don't find any interesting functions for me in glibc/sysdeps/unix/syscalls.list
.我知道 glibc 会生成一些系统调用,但我在
glibc/sysdeps/unix/syscalls.list
中没有找到任何有趣的函数。
I also extracted cold functions from libc.a
:我还从
libc.a
中提取了冷函数:
cd /usr/lib/x86_64-linux-gnu/
readelf -a --wide libc.a | egrep '\.cold' | awk '{print $NF}' > libc.a.cold
and compared them with readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
并将它们与
readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
进行比较readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
: readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
:
grep -f libc.a.cold hello.readelf
These are the matched functions:这些是匹配的功能:
__assert_fail_base.cold
_nl_load_domain.cold
_IO_new_fclose.cold
_IO_fflush.cold
_IO_puts.cold
_IO_wfile_underflow.cold
_IO_new_file_underflow.cold
_IO_fputs.cold
_IO_fwrite.cold
_IO_getdelim.cold
__printf_fp_l.cold
__printf_fphex.cold
And with grep -f libc.a.cold hello.readelf -v
I found the unmatched functions:并且使用
grep -f libc.a.cold hello.readelf -v
我发现了不匹配的功能:
read_encoded_value_with_base.cold
base_of_encoded_value.cold
execute_cfa_program.cold
uw_frame_state_for.cold
uw_install_context_1.cold
execute_stack_op.cold
uw_update_context_1.cold
uw_init_context_1.cold
uw_update_context.cold
_Unwind_RaiseException_Phase2.cold
_Unwind_GetGR.cold
_Unwind_SetGR.cold
_Unwind_Resume.cold
_Unwind_Resume_or_Rethrow.cold
size_of_encoded_value.cold
base_from_object.cold
base_from_cb_data.cold
read_encoded_value_with_base.cold
_Unwind_IteratePhdrCallback.cold
search_object.cold
base_of_encoded_value.cold
read_encoded_value_with_base.cold
Questions:问题:
libc.a
and the hello
binary located, and from which library are they loaded?libc.a
和hello
二进制文件的不匹配函数的源代码在哪里,它们是从哪个库加载的? Versions:版本:
glibc: ldd (Ubuntu GLIBC 2.31-0ubuntu9.7) 2.31
glibc:
ldd (Ubuntu GLIBC 2.31-0ubuntu9.7) 2.31
gcc: gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
gcc:
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Linux distro: Linux 发行版:
DISTRIB_ID=Ubuntu DISTRIB_RELEASE=20.04 DISTRIB_CODENAME=focal DISTRIB_DESCRIPTION="Ubuntu 20.04.4 LTS"
Kernel: 5.13.0-41-generic
内核:
5.13.0-41-generic
Functions do not necessarily have to be marked as cold using __attribute__((cold))
in order for GCC to realize that they are "cold".函数不一定必须使用
__attribute__((cold))
标记为冷,以便 GCC 意识到它们是“冷的”。 GCC can and will do this by itself when the appropriate optimizations are enabled.当启用适当的优化时,GCC 可以并且将自行执行此操作。
In particular, quoting from GCC's optimizations doc:特别是引用 GCC 的优化文档:
-freorder-blocks-and-partition
In addition to reordering basic blocks in the compiled function, in order to reduce number of taken branches, partitions hot and cold basic blocks into separate sections of the assembly and
.o
files, to improve paging and cache locality performance.除了在编译函数中重新排序基本块之外,为了减少采用的分支数量,将热和冷基本块划分为程序集和
.o
文件的单独部分,以提高分页和缓存局部性性能。This optimization is automatically turned off in the presence of exception handling or unwind tables (on targets using setjump/longjump or target specific scheme), for linkonce sections, for functions with a user-defined section attribute and on any architecture that does not support named sections.
在存在异常处理或展开表(在使用 setjump/longjump 或目标特定方案的目标上)、linkonce 部分、具有用户定义的部分属性的函数以及任何不支持命名的架构时,此优化会自动关闭部分。 When
-fsplit-stack
is used this option is not enabled by default (to avoid linker errors), but may be enabled explicitly (if using a working linker).当使用
-fsplit-stack
时,默认情况下不启用此选项(以避免链接器错误),但可以显式启用(如果使用工作链接器)。Enabled for x86 at levels
-O2
,-O3
,-Os
.在
-O2
、-O3
、-Os
级别为 x86 启用。
As you can see, this optimization is enabled by default at -O2
, -O3
and -Os
.如您所见,默认情况下,此优化在
-O2
、 -O3
和-Os
处启用。
A simple example of when such an automatic optimization could be applied would be a situation like the following:何时可以应用这种自动优化的一个简单示例如下所示:
void parent_function(int x) {
if (__builtin_expect(x == 1337, 1)) {
some_function(123);
} else {
some_function(456);
}
// ...
}
GCC can split some_function
(or even parent_function
) into some_function
and some_function.cold
, simplifying the internal logic of the functions. GCC 可以将
some_function
(甚至parent_function
)拆分为some_function
和some_function.cold
,简化函数的内部逻辑。 So in your case, those .cold
functions you see in the compiled binary are not actually defined in the source code as such, but rather produced by GCC automatically.因此,在您的情况下,您在编译后的二进制文件中看到的那些
.cold
函数实际上并未在源代码中定义,而是由 GCC 自动生成。
where I can find a source code of cold functions?
在哪里可以找到冷函数的源代码?
In glibc source code.在 glibc 源代码中。
I cannot find any functions from above marked with cold atribute
我找不到上面标有冷属性的任何功能
That is very odd, simple grep -R
is enough, but you might be interested in code indexing - clangd, GLOBAL tags, ctags, etc. You can interest yourself in the_silver_searcher for faster grep
.这很奇怪,简单的
grep -R
就足够了,但你可能对代码索引感兴趣——clangd、GLOBAL 标签、ctags 等。你可以对 the_silver_searcher 感兴趣以获得更快的grep
。
$ git clone git://git.launchpad.net/ubuntu/+source/glibc
Cloning into 'glibc'...
...
$ cd glibc/
$ grep -R --include '*.c' __assert_fail_base
assert/assert.c:__assert_fail_base (const char *fmt, const char *assertion, const char *file,
assert/assert.c: __assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"),
assert/assert-perr.c: __assert_fail_base (_("%s%s%s:%u: %s%sUnexpected error: %s.\n%n"),
So __assert_fail_base
is defined in assert/assert.c
.所以
__assert_fail_base
在assert/assert.c
中定义。 You can repeat the process for every function.您可以为每个功能重复该过程。
But it's much simpler to just type the function in google or find the project on github and search there.但是在 google 中输入函数或在 github 上找到项目并在那里搜索要简单得多。 And there is also https://code.woboq.org/ , which makes the task just trivial.
还有https://code.woboq.org/ ,这使任务变得微不足道。
Where is located source code of unmatched functions from libc.a and hello binary and from which library they loads?
来自 libc.a 和 hello 二进制文件的不匹配函数的源代码在哪里以及它们从哪个库加载?
That looks like inside libgcc and the Unwind
most probably in gcc libstdc++ .这看起来像在libgcc中,而
Unwind
很可能在gcc libstdc++中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.