Where are global variables located in the elf file

19,716

Solution 1

You can use objdump -t to view the symbol table:

$ objdump -t foo | grep -P '      \b(a|b|c|d|e|f)\b'
0000000000601034 l     O .data  0000000000000004              c
0000000000601040 l     O .bss   0000000000000004              d
0000000000601044 l     O .bss   0000000000000004              f.1710
0000000000601038 l     O .data  0000000000000004              e.1709
0000000000601048 g     O .bss   0000000000000004              b
0000000000601030 g     O .data  0000000000000004              a

You are right that b, d, and f are .bss while a, c, and e are .data. Whether the symbol is static or not is recorded in a separate flag of the symbol table—that’s the l or g flag in the second column.

The elf(5) man page says that these are recorded using the STB_LOCAL and STB_GLOBAL values for the st_info member of the symbol table. /usr/include/elf.h says that STB_GLOBAL is 1, while STB_LOCAL is 0. There is a macro ST_BIND to retrieve the binding bits of the st_info field.


There are tons of other flags for objdump—see the man page. objdump works with all architectures, but there is also an elfdump tool that does a bit better job of showing elf-specific stuff. objdump and the underlying BFD library can do a bad job of showing some file-format-specific data.

Solution 2

In general, the data segment of the executable contains initialized global/static variables and the BSS segment contains uninitialized global/static variables.

When the loader loads your program into memory, the unitialized global/static variables are automatically zero-filled.

In C, static variables (initialized or not) inside a function just mean the variables have local/function scope (sometimes referred to as internal static), but they still live in the Data/BSS segments depending on whether or not they are initialized.

So regardless of how many times fun() gets called, the static variables are initilized only once when the program is loaded.

Variables defined as static and outside any functions still live in either the data or bss segments, but have file scope only.

When your code is compiled, there is an import and export list that is part of each object file and is used by the linkage editor. Your static variables will not be in the export list and therefore inaccessable to other object files.

By excluding the static keyword, your global variables are placed in the export list and can be referred to by other object modules and the linkage editor will be able to find the symbols when creating the executable.

For a pictoral view:

+--------- TEXT ---------+  Low memory
| main()                 |
| fun()                  |
+--------- DATA ---------+
| int a (global scope)   |
| int c (file scope)     |
| int e (function scope) |
+---------- BSS ---------+
| int b (global scope)   |
| int d (file scope)     |
| int f (function scope) |
+------------------------+
Share:
19,716
CrystalJake
Author by

CrystalJake

Android Framework engineer

Updated on June 13, 2022

Comments

  • CrystalJake
    CrystalJake almost 2 years

    I want to learn about elf files, but when I think of global variables, global static variables and scope static variables, I have some confusion. For example:

    int a = 2;
    int b;
    
    static int c = 4;
    static int d;
    
    void fun(){
      static int e = 6;
      static int f;
    }
    
    
    int main(void){
       fun();
    }
    

    Who can tell which segment each variable belongs to? in my opinion, b, d and f belong to the .bss segment and a,c and e belong to the data segment, but I don't know the difference between global static variables and global variables in elf file.

  • CrystalJake
    CrystalJake almost 11 years
    I can't understand what is the export list.Is it symbol table?
  • ffhaddad
    ffhaddad almost 11 years
    In short, part of each .o (object file) is an export list (a list of external symbols -- global variables/functions) which are visible to other object files. Also, there is an import list (global variables/functions) which are symbols referred to within the object file but defined elsewhere. During the link phase of compilation the linkage editor uses these lists to tie symbols together.