---
# System prepended metadata

title: Symbol table 觀察紀錄
tags: [MVMC-lab, Firmware]

---

# 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
    ```
:::


