2013-06-18 13 views
7

Niedawno chcę się nauczyć o pewnej wiedzy o pliku elfa, ale gdy napotykam zmienną globalną, globalną zmienną statyczną i zmienną statyczną zakresu, mam małe zamieszanie, na przykład:Gdzie jest zmienna globalna w pliku elfa

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(); 
} 

Kto może powiedzieć, który segment należący każda zmienna do? moim zdaniem, b, d, f, należą do segmentu BSS a, C, e należą do segmentu danych, ale nie znam różnicę między globalnym statyczne zmienna i globalna varibale w pliku elfa.

Odpowiedz

11

Można użyć objdump -t aby zobaczyć tablicę symboli:

$ 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 

Masz rację, że b, d i f.bss podczas a, c, a e.data. To, czy symbol jest statyczny, czy nie, zapisywane jest w oddzielnej banderoli tablicy symboli - w drugim polu jest to flaga l lub .

elf(5) man page mówi, że są one rejestrowane przy użyciu wartości STB_LOCAL i STB_GLOBAL na członka tablicy symboli st_info. /usr/include/elf.h mówi, że STB_GLOBAL ma wartość 1, natomiast STB_LOCAL ma wartość 0. Istnieje makro ST_BIND, aby pobrać bity wiążące z pola st_info.


Istnieje mnóstwo innych flagi dla objdump -patrz na man page. objdump działa ze wszystkimi architekturami, ale istnieje również narzędzie elfdump, które nieco lepiej pokazuje pokazywanie konkretnych elementów. objdump i bazowa biblioteka BFD może źle wyświetlać niektóre dane specyficzne dla formatu pliku.

7

Ogólnie segment danych pliku wykonywalnego zawiera zainicjalizowane zmienne globalne/statyczne, a segment BSS zawiera niezainicjalizowane zmienne globalne/statyczne.

Gdy program ładujący ładuje program do pamięci, ujednolicone zmienne globalne/statyczne są automatycznie zerowane.

W języku C zmienne statyczne (zainicjowane lub nie) wewnątrz funkcji oznaczają, że zmienne mają zasięg lokalny/funkcja (czasami określane jako wewnętrzne statyczne), ale wciąż żyją w segmentach danych/BSS w zależności od tego, czy są inicjalizowane.

Niezależnie od tego, ile razy funkcja fun() zostanie wywołana, zmienne statyczne są inicjalizowane tylko jeden raz podczas ładowania programu.

Zmienne zdefiniowane jako statyczne i poza dowolnymi funkcjami nadal znajdują się w segmentach danych lub bss, ale mają tylko zasięg pliku.

Po skompilowaniu kodu istnieje lista importów i eksportów, która jest częścią każdego pliku obiektu i jest używana przez edytor linków. Twoje zmienne statyczne nie znajdą się na liście eksportu, a zatem nie będą dostępne dla innych plików obiektów.

Wykluczając słowo kluczowe static, zmienne globalne są umieszczane na liście eksportu i mogą być przywoływane przez inne moduły obiektów, a edytor połączeń będzie mógł znaleźć symbole podczas tworzenia pliku wykonywalnego.

Dla obrazkowe widzenia:

+--------- 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) | 
+------------------------+ 
+0

nie mogę zrozumieć, co jest list.Is eksportować stół symbol? – CrystalJake

+0

W skrócie, część każdego .o (pliku obiektowego) jest listą eksportową (lista zewnętrznych symboli - globalne zmienne/funkcje), które są widoczne dla innych plików obiektów. Istnieje również lista importu (globalne zmienne/funkcje), które są symbolami przywoływanymi w pliku obiektów, ale zdefiniowanymi gdzie indziej. Podczas fazy łączenia kompilacji edytor połączeń wykorzystuje te listy do powiązania symboli. – ffhaddad