iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
Software Development

30 天 CMake 跨平台之旅系列 第 17

[Day 17] 什麼是 Symbols?

  • 分享至 

  • xImage
  •  

本日內容

  • 蛤? Symbols?
  • 好用的分析工具 "們"
  • 預告

Day 17 - Colab

今天的內容會複習一下 symbols 是什麼, 以及 linker 是如何把一堆 object files 合併成一個大 ELF 的, 並以 C++ 為例, 用 CMake build 出 libraries, executable, object files 來細看每種檔案裡面包含了哪些東西

那麼這跟 CMake 有什麼關係呢?
希望大家看了今天的內容後, 對 Day 18 將要介紹的 Link Dependencies 能有更多了解, 在日後遇到問題時, 不管是去看 raw linker command 或是 objdump 去看 op 等等, 都能看懂並自己 debug

如果對 C/C++ 已經很熟悉的人可以跳過今天的內容, 可能太簡單了😅

蛤? Symbols?

Day 11 在介紹 static libraries 和 shared libraries 時有簡單提過, symbols 包含了各種 變數
但嚴格來說, 以一個 source file 為例, symbols 包含了該檔案中除 static variable 以外宣告的 所有 變數, 由於 static variables 是 local scope, 而 symbols 最主要的目的是讓 linker 能夠找到 reference symbol 需要的變數的真正位置, 才能在最後產生 ELF 時順利 relocate 並塞到字段, 所以僅需要 global scope 的變數

當專案架構越來越複雜, 更多的 libraries 被建立或是引進了更多外部套件, Dependency Tree 的關係也會變得複雜, 就容易產生 build error

所以, 下面會簡單介紹一些方便看 binary 的工具

好用的分析工具 "們"

readelf

我們可以用 readelf 來檢查 binary (通常是 ELF), 可以看到 relocation table, symbols 等等, 關於什麼是 ELF 請見 elf(5)

我們可以用以下指令看看最後可執行檔的 section headers 有哪些

readelf -SW build/src/Main | less

There are 32 section headers, starting at offset 0x3c70:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000000318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000000338 000338 000030 00   A  0   0  8
  [ 3] .note.gnu.build-id NOTE            0000000000000368 000368 000024 00   A  0   0  4
  [ 4] .note.ABI-tag     NOTE            000000000000038c 00038c 000020 00   A  0   0  4
  [ 5] .gnu.hash         GNU_HASH        00000000000003b0 0003b0 000030 00   A  6   0  8
  [ 6] .dynsym           DYNSYM          00000000000003e0 0003e0 0001f8 18   A  7   1  8
  [ 7] .dynstr           STRTAB          00000000000005d8 0005d8 0002dc 00   A  0   0  1
  [ 8] .gnu.version      VERSYM          00000000000008b4 0008b4 00002a 02   A  6   0  2
  [ 9] .gnu.version_r    VERNEED         00000000000008e0 0008e0 0000a0 00   A  7   3  8
  [10] .rela.dyn         RELA            0000000000000980 000980 000168 18   A  6   0  8
  [11] .rela.plt         RELA            0000000000000ae8 000ae8 0000f0 18  AI  6  25  8
  [12] .init             PROGBITS        0000000000001000 001000 00001b 00  AX  0   0  4
  [13] .plt              PROGBITS        0000000000001020 001020 0000b0 10  AX  0   0 16
  [14] .plt.got          PROGBITS        00000000000010d0 0010d0 000020 10  AX  0   0 16
  [15] .plt.sec          PROGBITS        00000000000010f0 0010f0 0000a0 10  AX  0   0 16
  [16] .text             PROGBITS        0000000000001190 001190 000302 00  AX  0   0 16
  [17] .fini             PROGBITS        0000000000001494 001494 00000d 00  AX  0   0  4
  [18] .rodata           PROGBITS        0000000000002000 002000 000013 00   A  0   0  4
  [19] .eh_frame_hdr     PROGBITS        0000000000002014 002014 00005c 00   A  0   0  4
  [20] .eh_frame         PROGBITS        0000000000002070 002070 00017c 00   A  0   0  8
  [21] .gcc_except_table PROGBITS        00000000000021ec 0021ec 00001f 00   A  0   0  1
  [22] .init_array       INIT_ARRAY      0000000000003d28 002d28 000018 08  WA  0   0  8
  [23] .fini_array       FINI_ARRAY      0000000000003d40 002d40 000008 08  WA  0   0  8
  [24] .dynamic          DYNAMIC         0000000000003d48 002d48 000210 10  WA  7   0  8
  [25] .got              PROGBITS        0000000000003f58 002f58 0000a8 08  WA  0   0  8
  [26] .data             PROGBITS        0000000000004000 003000 000018 00  WA  0   0  8
  [27] .bss              NOBITS          0000000000004040 003018 000140 00  WA  0   0 64
  [28] .comment          PROGBITS        0000000000000000 003018 00002b 01  MS  0   0  1
  [29] .symtab           SYMTAB          0000000000000000 003048 0005b8 18     30  27  8
  [30] .strtab           STRTAB          0000000000000000 003600 000542 00      0   0  1
  [31] .shstrtab         STRTAB          0000000000000000 003b42 00012c 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

objdump

也可以用 objdump 來查看 object files 的 op, 比如

!objdump -d build/src/CMakeFiles/Main.dir/main.cpp.o

build/src/CMakeFiles/Main.dir/main.cpp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:	f3 0f 1e fa          	endbr64 
   4:	55                   	push   %rbp
   5:	48 89 e5             	mov    %rsp,%rbp
   8:	53                   	push   %rbx
   9:	48 83 ec 38          	sub    $0x38,%rsp
   d:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
...

預告

有了這些概念之後, 下一篇會來介紹一些 CMake 在建立 Link Dependency Tree 時的注意事項


上一篇
[Day 16] 管理 Library 版本
下一篇
[Day 18] 注意! Link dependencies
系列文
30 天 CMake 跨平台之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言