【问题标题】:Nearly duplicate symbols from readelf at same address来自同一地址的 readelf 几乎重复的符号
【发布时间】:2023-04-03 16:14:01
【问题描述】:

我正在使用 readelf 来找出二进制文件为何如此之大,但我对输出感到困惑。或者我的二进制文件链接非常错误。现在二进制文件大约是 380MB,如果我这样做:

readelf -W -s 二进制文件 | awk 'NR > 3 { sum += $3 } END { print sum }'

我得到 236221726 字节。似乎很低,但也许我缺少静态符号或没有。但如果我这样做:

readelf -W -s 二进制文件 |排序 -n -r -k 3 |少

我看到了:

172766: 000000000cf8d960 99993 FUNC 全局默认值 10 符号A

147338: 000000000cf8d960 99993 FUNC 全局默认值 10 符号B

132791: 000000000cf8d960 99993 FUNC 全局默认值 10 符号A

107363: 000000000cf8d960 99993 FUNC GLOBAL DEFAULT 10 符号B

其中 symbolA 和 symbolB 仅相差 1 个字符,并且对同一事物进行分解。

所以,我的问题: 1)如果这些东西具有相同的地址,我的二进制文件中实际上有四个副本吗? 2)如果没有四个副本,并且这些是别名,那么 readelf 不应该报告吗? 3)如果是四个副本,如何以及为什么?我假设我在做一些不好的链接方式。 4) 如果没有四个副本,那么来自 readelf 的总大小远低于二进制文件的实际大小 - 为什么?

编辑:添加更多信息...上面的 readelf 输出来自完全链接的二进制文件。仅查看包含 symbolA/symbolB 的 .o,readelf 仍会在同一地址报告每个 symbolA 和 symbolB 的 1 个副本。

但是如果我 objdump -d .o 文件,我只会看到 symbolA 的程序集。

那么 - objdump 或 readelf 是“错误的”吗?

【问题讨论】:

    标签: c++ linux linker readelf


    【解决方案1】:

    如果您将函数 definition 放在头文件中,然后将此头文件包含在不同的源文件中,则每次包含都会生成不同的函数(嗯,除非它在特定源文件的任何地方都内联)。如果不查看您的消息来源,很难判断,但情况可能就是这样。

    考虑在单独的源文件中移动大的不可内联函数,在相应的标题中只留下 声明。这可能会奏效。

    【讨论】:

    • symbolA/B解码成的函数不在头文件中,而是在cpp文件中。
    • @BraxtonThomason 是的,这是有道理的。但是符号的实际地址都是相等的——它们都指向000000000cf8d960。您是否考虑过从二进制文件中删除调试符号?
    • 这是编译时使用 -O3 而没有 -g。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多