2011-02-10 6 views
18

Chiunque ha un riferimento per la rappresentazione di va_list nell'ABI x86_64 (quello utilizzato su Linux)? Sto cercando di eseguire il debug del codice in cui la pila o argomenti sembrano corrotta e sarebbe davvero aiutare a capire quello che sto suppone di essere visto ...Qual è il formato della struttura va_list x86_64?

+11

Per chi ama il vicinato: cosa stai pensando? Non è fuori tema; si tratta di programmare su Linux! –

risposta

24

ho fatto il mio commento in una risposta.

This may help. È un riferimento, anche se leggero.

la variabile inizia riferimento lista degli argomenti a pagina 50, allora si perviene, pagina 52-53 documenti va_list:

Il tipo va_list

Il tipo va_list è una matrice contenente un elemento singolo di una struttura contenente le informazioni necessarie per implementare la macro va_arg . La definizione C de fi di va_list tipo è riportata nella figura 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]; 

il va_start Macro

La macro va_start inizializza la struttura come segue:

reg_save_area I punti dell'elemento a l'inizio dell'area di salvataggio del registro.

overflow_arg_area Questo puntatore viene utilizzato per recuperare gli argomenti passati nello stack . Viene inizializzato con l'indirizzo del primo argomento passato su lo stack, se presente, e quindi sempre aggiornato per indicare l'inizio dell'argomento successivo nello stack.

gp_offset L'elemento contiene l'offset in byte da reg_save_area al luogo dove parato disponibile successivo generale scopo registro argomento. Nel caso tutti i registri degli argomenti sono stati scaricati , è impostato sul valore 48 (6 * 8).

fp_offset L'elemento contiene l'offset in byte dal reg_save_area al luogo cui è salvato successivo disponibile floating point registro l'argomento. Nel caso tutti i registri degli argomenti sono stati scaricati , è impostato sul valore 304 (6 * 8 + 16 * 16).

+0

Grazie. Sto accettando questo e anche mettendo una spiegazione del problema e come l'ho risolto come un'altra risposta. –

+0

@R ..: Felice di aiutare. – Skurmedel

+0

Sono abbastanza sicuro che questi registri "in virgola mobile" siano in realtà registri SSE e che ce ne siano solo 8. –

13

Si scopre che il problema è che gcc sta rendendo va_list un tipo di matrice.La mia funzione era della firma:

void foo(va_list ap); 

e volevo passare un puntatore a ap a un'altra funzione, così ho fatto:

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

Purtroppo, tipi di array decadimento ai tipi di puntatore in liste di argomenti di funzione , quindi piuttosto che passare un puntatore alla struttura originale, stavo passando un puntatore a un puntatore.

Per aggirare il problema, ho cambiato il codice per:

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

Questa è l'unica soluzione portatile ho potuto trovare, che tiene conto sia la possibilità che va_list è un tipo di matrice e la possibilità che non lo è.

+0

Non potresti aver appena fatto 'pippo'? Prendere un argomento di tipo' va_list * '? – caf

+1

@caf: 'foo' ha una firma fissa che non posso cambiare. E anche se no, le funzioni 'v *' accettano sempre un argomento 'va_list', non un argomento' va_list * '. Questa è una convenzione standard e sarebbe una seccatura per gli utenti della funzione violarla. –

+0

Perché hai dovuto passare un puntatore a ap2 nella chiamata a bar()? – ydroneaud