链接器在函数/方法和变量级别是细粒度的。如果未引用函数、方法或变量,则无需将其包含在链接的二进制文件中。
您可以使用objdump 程序自行检查(您可能需要在系统上安装它;还有其他工具可以读取可能已经安装的 .elf 二进制文件)。
这是一个简单的程序。这是使用 Arduino 框架的 C++,但它使用与 ESP-IDF 相同的工具链,因为它是基于它构建的。我包括了 WiFi,只是给它一点重量。
#include <Arduino.h>
#include <WiFi.h>
void ignore_me() {
Serial.println("this will never happen");
Serial.println("this code won't even be linked in");
}
void setup() {
WiFi.begin("foo", "bar");
}
void loop() {
}
构建完成后就可以运行了
objdump --syms firmware.elf
查看符号列表。例如,我们可以这样找到setup() 函数:
objdump --syms firmware.elf | grep setup
返回:
40120cbc l F .flash.text 00000032 setup_tcp
4012cd18 l F .flash.text 00000013 __esp_stack_guard_setup
4010a2c8 g F .flash.text 0000007d hostapd_setup_wpa_psk
400f8cb4 g F .flash.text 0000032f esf_buf_setup
400d8f18 g F .flash.text 0000008e ieee80211_setup_basic_htrates
400d9580 g F .flash.text 000000da ieee80211_setup_phy_mode
4012edd4 g F .flash.text 00000037 esp_setup_syscall_table
4008bb58 g F .iram0.text 00000000 _frxt_setup_switch
400e02cc g F .flash.text 00000141 ieee80211_send_setup
4013c320 g F .flash.text 00000084 ieee80211_setup_lr_rates
400d8e4c g F .flash.text 000000c6 ieee80211_setup_htrates
400d965c g F .flash.text 00000134 ieee80211_setup_rates
40058cc8 g *ABS* 00000000 __swsetup_r
400e2324 g F .flash.text 00000101 ieee80211_setup_ratetable
400d04a8 g F .flash.text 0000001c _Z5setupv
4013c3a4 g F .flash.text 00000007 ieee80211_setup_rateset
40026c84 g *ABS* 00000000 lmp_setup_cmp_handler
符号_Z5setupv 对应于设置功能。多余的字符是由于 C++ 添加了类型信息(例如,结尾的 v 表示它的参数是 void)。
跑步
objdump --syms firmware.elf | grep ignore
将不返回任何内容,因为函数 ignore_me() 未包含在链接的二进制文件中。
如果我们返回并修改setup() 以调用ignore_me() 并再次运行objdump,我们将看到如下内容:
400d04ac g F .flash.text 0000001a _Z9ignore_mev
表示现在 ignore_me() 已包含在二进制文件中,因为它正在被调用。
0000001a 是与符号关联的代码的大小。您可以使用objdump 的输出来查找二进制文件中最大的函数;您也许可以重写它以消除其中的一些。 (剧透:printf() 及其亲属通常很大。)
您还可以将objdump 与.a 和.o 文件一起使用。