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?
Odpowiedz
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).
Dzięki. Akceptuję to, a także wyjaśniam problem i jak rozwiązałem go jako kolejną odpowiedź. –
@R ..: Cieszę się, że mogę Ci pomóc. – Skurmedel
Jestem pewien, że te rejestry "zmiennoprzecinkowe" są w rzeczywistości rejestrami SSE i że jest ich tylko 8. –
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.
Nie możesz właśnie '' foo' zająć argument typu 'va_list *'? – caf
@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. –
Dlaczego trzeba przekazać wskaźnik do ap2 w wywołaniu bar()? – ydroneaud
Dla bliskich: o czym myślisz? Nie jest poza tematem; chodzi o programowanie w Linuksie! –