2011-02-10 15 views
18

Ktoś ma odniesienia do reprezentacji va_list w ABI x86_64 (ten używany na Linux)? Usiłuję do debugowania kodu, gdzie stos lub argumenty wydają uszkodzony i to naprawdę pomaga zrozumieć, co mam powinien do zobaczenia ...Jaki jest format struktury va_list x86_64?

+11

Dla bliskich: o czym myślisz? Nie jest poza tematem; chodzi o programowanie w Linuksie! –

Odpowiedz

24

zrobiłem mój komentarz na odpowiedź.

This may help. To odniesienie, choć lekkie.

zmiennej startów Lista Referencyjna Argument na stronie 50, a następnie przechodzi na str 52-53 dokumenty va_list:

Type va_list

Typ va_list jest tablica zawierająca pojedynczy element jednej struktury zawierający niezbędną informację do wykonania makra va_arg . Definicja C de fi va_list typu jest przedstawione w fi Güre 3,34

// Figure 3.34 
typedef struct { 
    unsigned int gp_offset; 
    unsigned int fp_offset; 
    void *overflow_arg_area; 
    void *reg_save_area; 
} va_list[1]; 

va_start makro

va_start makro inicjalizuje strukturę następująco:

reg_save_area punkty elementu do początek obszaru zapisywania rejestru.

overflow_arg_area Ten wskaźnik jest używany do pobierania argumentów przekazanych na stosie . Jest on inicjalizowany adresem pierwszego argumentu przekazanego na stosu, jeśli taki istnieje, a następnie zawsze zaktualizowany tak, aby wskazywał początek następnego argumentu na stosie.

gp_offset Element posiada offset w bajtach od reg_save_area do miejscu, gdzie obok ogólnie dostępny rejestr argumentu cel został zapisany. W przypadku wszystkich rejestrów argumentów wyczerpanych ustawiona jest na wartość 48 (6 * 8).

fp_offset Element posiada przesunięcie w bajtach od reg_save_area do miejscu dostępny następny punkt rejestr argumentu fl oating został zapisany. W przypadku wszystkie rejestry argumentów zostały wyczerpane, , jest ustawiona na wartość 304 (6 * 8 + 16 * 16).

+0

Dzięki. Akceptuję to, a także wyjaśniam problem i jak rozwiązałem go jako kolejną odpowiedź. –

+0

@R ..: Cieszę się, że mogę Ci pomóc. – Skurmedel

+0

Jestem pewien, że te rejestry "zmiennoprzecinkowe" są w rzeczywistości rejestrami SSE i że jest ich tylko 8. –

13

Okazuje się, że problem polegał na tym, że gcc tworzy va_list typ tablicy.Moja funkcja była z podpisem:

void foo(va_list ap); 

i chciałem przekazać wskaźnik do ap do innej funkcji, tak zrobiłem:

void foo(va_list ap) 
{ 
    bar(&ap); 
} 

Niestety, typy tablic rozpad typów wskaźnikowych na listach argumentem funkcji , więc zamiast przekazywać wskaźnik do oryginalnej struktury, przekazywałem wskaźnik do wskaźnika.

Aby obejść ten problem, zmieniłem kod do:

void foo(va_list ap) 
{ 
    va_list ap2; 
    va_copy(ap2, ap); 
    bar(&ap2); 
    va_end(ap2); 
} 

Jest to jedyny przenośny rozwiązanie mogłam wymyślić, co stanowi zarówno możliwość, że va_list jest typu array oraz możliwość że tak nie jest.

+0

Nie możesz właśnie '' foo' zająć argument typu 'va_list *'? – caf

+1

@caf: 'foo' ma ustalony podpis, którego nie mogę zmienić. A nawet jeśli nie, funkcje 'v *' zawsze pobierają argument 'va_list', a nie' va_list * '. Jest to standardowa konwencja i denerwujące dla użytkowników funkcji byłoby jej naruszenie. –

+0

Dlaczego trzeba przekazać wskaźnik do ap2 w wywołaniu bar()? – ydroneaud

Powiązane problemy