У меня есть программа hello world на C:
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
Скомпилируй gcc -static hello.c -o hello
В 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.
When profile feedback is available, via -fprofile-use, cold functions are automatically detected and this attribute is ignored.
Соответственно, я скачать glibc и переключаюсь на коммит 160f6c36a374841ee6e2bf2ee0ba05b70634978e
, что указывает на мою версию git rev-list -n 1 $(git tag | grep 2.31-0ubuntu9.7)
, но после всех этих действий я не могу найти ни одной функции сверху, помеченной атрибутом холодный.
Я знаю, что glibc генерирует некоторые системные вызовы, но не нахожу в glibc/sysdeps/unix/syscalls.list
интересных для себя функций.
Я также извлек функции холодный из libc.a
:
cd /usr/lib/x86_64-linux-gnu/
readelf -a --wide libc.a | egrep '\.cold' | awk '{print $NF}' > libc.a.cold
и сравнил их с readelf -a --wide hello | egrep '\.cold' | awk '{print $NF}' > hello.readelf
:
grep -f libc.a.cold hello.readelf
Это согласованные функции:
__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
А с 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
Вопросы:
libc.a
и бинарника hello
и из какой библиотеки они загружены?Версии:
glibc: ldd (Ubuntu GLIBC 2.31-0ubuntu9.7) 2.31
гкк: gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
дистрибутив линукс:
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION = "Ubuntu 20.04.4 LTS"
Ядро: 5.13.0-41-generic
@KamilCuk это не то, что ищет ОП. ОП хочет понять, откуда взялся .cold
, поскольку в исходном коде такой атрибут не объявлен.
where I can find a source code of cold functions?
В исходном коде glibc.
I cannot find any functions from above marked with cold atribute
Это очень странно, достаточно простого 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"),
Итак, __assert_fail_base
определяется в assert/assert.c
. Вы можете повторить процесс для каждой функции.
Но гораздо проще просто набрать функцию в гугле или найти проект на гитхабе и поискать там. А еще есть https://code.woboq.org/, что делает задачу просто тривиальной.
Where is located source code of unmatched functions from libc.a and hello binary and from which library they loads?
Похоже, внутри libgcc, а Unwind
, скорее всего, в gcc-libstdС++.
Функции не обязательно должны быть помечены как холодные с помощью __attribute__((cold))
, чтобы GCC понял, что они «холодные». GCC может и будет делать это сам, когда включены соответствующие оптимизации.
В частности, цитируя документ 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.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. 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).Enabled for x86 at levels
-O2
,-O3
,-Os
.
Как видите, эта оптимизация включена по умолчанию в -O2
, -O3
и -Os
.
Простым примером применения такой автоматической оптимизации мог может быть следующая ситуация:
void parent_function(int x) {
if (__builtin_expect(x == 1337, 1)) {
some_function(123);
} else {
some_function(456);
}
// ...
}
GCC может разбивать some_function
(или даже parent_function
) на some_function
и some_function.cold
, упрощая внутреннюю логику функций. Итак, в вашем случае те функции .cold
, которые вы видите в скомпилированном двоичном файле, являются нет фактически определенными в исходном коде как таковые, а скорее создаются GCC автоматически.
after all of this actions I cannot find any functions from above marked with cold atribute
Итак, как вы искали? Простойgrep -R
должен дать вам результаты.