找到导致函数被链接的调用链

FMa*_*iro 6 c++ linker static-analysis

我正在开发一个嵌入式系统,在使用 nm 分析二进制文件时,我发现了许多来自标准库函数的符号,例如:

00001524 std::time_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_via_format(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, tm*, char const*) const [clone .localalias]
Run Code Online (Sandbox Code Playgroud)

这意味着有一个std::time_get函数被链接进来,该函数大小为 1524 字节。我想找出是什么调用链导致了调用,std::time_get因为我实际上并没有在代码的任何部分中引用它。

尝试使用链接器标志--cref并查看映射文件,我可以找到该符号,但找不到调用它的内容。它只告诉我libstdc++_nano.a(locale-inst.o)引用它:

.text._ZNKSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE21_M_extract_via_formatES3_S3_RSt8ios_baseRSt12_Ios_IostateP2tmPKc
                0x00000000080a07bc      0x5fc /opt/st/stm32cubeide_1.10.1/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.0.202111181127/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+dp/hard/libstdc++_nano.a(locale-inst.o)
                0x00000000080a07bc                std::time_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_via_format(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, tm*, char const*) const
Run Code Online (Sandbox Code Playgroud)

我怎样才能从那里找到呼叫者?

Emp*_*ian 1

您可以使用链接器-y标志来回答这个问题(尽管这非常乏味)。

例子:

// foo.c
int foo() { return 42; }

// bar.c
int bar() { return foo(); }

// main.c
int main() { return bar(); }
Run Code Online (Sandbox Code Playgroud)
gcc -w -c main.c foo.c bar.c
ar r libfoo.a foo.o
ar r libbar.a bar.o

gcc main.o -L. -lbar -lfoo -Wl,-y,foo
 
/usr/bin/ld: ./libbar.a(bar.o): reference to foo
/usr/bin/ld: ./libfoo.a(foo.o): definition of foo
Run Code Online (Sandbox Code Playgroud)

这告诉您该foo链接已被选中,因为bar.o有对其的引用。重复bar

gcc main.o -L. -lbar -lfoo -Wl,-y,bar
/usr/bin/ld: main.o: reference to bar
/usr/bin/ld: ./libbar.a(bar.o): definition of bar
Run Code Online (Sandbox Code Playgroud)

您还可以使用该-M标志来获取相同的信息:

gcc main.o -L. -lbar -lfoo -Wl,-M
Run Code Online (Sandbox Code Playgroud)

将有类似这样的输出:

 .text          0x0000000000001070       0xb9 /usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o
 .text          0x0000000000001129       0x10 main.o
                0x0000000000001129                main           <<<---
 .text          0x0000000000001139       0x10 ./libbar.a(bar.o)
                0x0000000000001139                bar            <<<---
 .text          0x0000000000001149        0xb ./libfoo.a(foo.o)
                0x0000000000001149                foo            <<<---
Run Code Online (Sandbox Code Playgroud)

标记<<<---显示哪个符号导致对应的符号.o被拉入链接。