简体   繁体   English

glibc 中“冷”函数的源代码在哪里?

[英]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 postfixreadelf -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

From here :这里

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:问题:

  1. Can someone please help me to figure out where I can find a source code of cold functions?有人可以帮我弄清楚在哪里可以找到函数的源代码吗?
  2. Where is the source code of unmatched functions from libc.a and the hello binary located, and from which library are they loaded?来自libc.ahello二进制文件的不匹配函数的源代码在哪里,它们是从哪个库加载的?

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_functionsome_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_baseassert/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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM