# Symbol table 觀察紀錄 ###### tags: `Firmware` `MVMC-lab` ## TODO - 增加新的變數型態 ```c int global_uninit_var; // 全域未初始化變數 int global_init0_var = 0; // 全域初始化為 0 變數 int global_init_var = 66; // 全域初始化變數 static int global_static_uninit_var; // 全域未初始化靜態變數 static int global_static_init0_var = 0; // 全域初始化為 0 靜態變數 static int global_static_init_var = 99; // 全域初始化靜態變數 int main(void) { int local_uninit_var; // 區域未初始化變數 int local_init0_var = 0; // 區域初始化為 0 變數 int local_init_var = 10; // 區域初始化變數 static int local_static_uninit_var; // 區域未初始化靜態變數 static int local_static_init0_var = 0; // 區域初始化為 0 靜態變數 static int local_static_init_var = 77; // 區域初始化靜態變數 return 0; } ``` :::info [延伸討論](https://hackmd.io/_kFdsNH2RlS5TAvcAzoDSA) ::: ## 實驗步驟 - **初始化為 0 的全域變數** ```c= int i = 0; int main(void) { return 0; } ``` - **初始化為非 0 的全域變數** ```c= int i = 1; int main(void) { return 0; } ``` - **未初始化的全域變數** ```c= int i; int main(void) { return 0; } ``` 設計以上三種程式段落,使用 avr-gcc 產生 .o 檔案 使用 avr-objdump 觀察 symbol table ## Objdump 工具 ```shell objdump - display information from object files ``` 我們可以使用 Objdump 工具觀察編譯過程中的 symbol table. 以下節錄自 objdump manual ```shell -t --syms Print the symbol table entries of the file. This is similar to the information provided by the nm program, although the display format is different. The format of the output depends upon the format of the file being dumped, but there are two main types. One looks like this: [ 4](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss [ 6](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 fred where the number inside the square brackets is the number of the entry in the symbol table, the sec number is the section number, the fl value are the symbol's flag bits, the ty number is the symbol's type, the scl number is the symbol's storage class and the nx value is the number of auxiliary entries associated with the symbol. The last two fields are the symbol's value and its name. The other common output format, usually seen with ELF based files, looks like this: 00000000 l d .bss 00000000 .bss 00000000 g .text 00000000 fred Here the first number is the symbol's value (sometimes referred to as its address). The next field is actually a set of characters and spaces indicating the flag bits that are set on the symbol. These characters are described below. Next is the section with which the symbol is associated or *ABS* if the section is absolute (ie not connected with any section), or *UND* if the section is referenced in the file being dumped, but not defined there. After the section name comes another field, a number, which for common symbols is the alignment and for other symbol is the size. Finally the symbol's name is displayed. The flag characters are divided into 7 groups as follows: "l" "g" "u" "!" The symbol is a local (l), global (g), unique global (u), neither global nor local (a space) or both global and local (!). A symbol can be neither local or global for a variety of reasons, e.g., because it is used for debugging, but it is probably an indication of a bug if it is ever both local and global. Unique global symbols are a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use. "w" The symbol is weak (w) or strong (a space). "C" The symbol denotes a constructor (C) or an ordinary symbol (a space). "W" The symbol is a warning (W) or a normal symbol (a space). A warning symbol's name is a message to be displayed if the symbol following the warning symbol is ever referenced. "I" "i" The symbol is an indirect reference to another symbol (I), a function to be evaluated during reloc processing (i) or a normal symbol (a space). "d" "D" The symbol is a debugging symbol (d) or a dynamic symbol (D) or a normal symbol (a space). "F" "f" "O" The symbol is the name of a function (F) or a file (f) or an object (O) or just a normal symbol (a space). ``` ## 實驗結果 - 宣告全域變數i並且初始化非0 ```asm= 00000000 g O .data 00000002 i ``` - 宣告全域變數i並且初始化為0 ```asm= 00000000 g O .bss 00000002 i ``` - 宣告全域變數並且不初始化 ```asm= 00000002 O *COM* 00000001 i ``` .data 理論上存放的是初始化過的變數 .bss 存放的是未經初始化的變數 但就結果上來看初始化為零不知為何存放在 bss 且未經初始化的變數放在一個叫做 COM 的 section 並且代表 global 的 g flag 及記憶體大小都變了 ## 參考資料 - [ELF中的.bss section和COMMON section](http://swaywang.blogspot.com/2012/06/elfbss-sectioncommon-section.html) - [.bss vs COMMON: what goes where?](https://stackoverflow.com/questions/16835716/bss-vs-common-what-goes-where) :::info 文章中提到gcc在某版本前會將初始為 0 的變數放進 .bss 中,將未初始化的變數放入 COMMON section,而 COMMON section 作為 linker merge 前的暫時儲存區,之後會依情況安排至其他資料區段,但 embedded system 最後都會放入 .bss 一起初始化為零。 - 驗證 ```shell= avr-gcc test.o -o test.elf avr-objdump -t test.elf ``` - 輸出 ```asm= 00800100 g O .bss 00000002 i ``` :::