¿Cuál es el formato de la estructura va_list x86_64?

¿Alguien tiene una referencia para la representación de va_list en el x86_64 ABI (el usado en Linux)? Estoy intentando depurar algún código donde la stack o los argumentos parecen corruptos y realmente ayudaría a entender lo que se supone que debo ver …

Hice mi comentario en una respuesta.

Esto puede ayudar . Es una referencia, aunque ligera.

La referencia de la lista de argumentos variables comienza en la página 50, luego continúa, página 52-53 documentos va_list :

El tipo va_list

El tipo va_list es una matriz que contiene un único elemento de una estructura que contiene la información necesaria para implementar la macro va_arg. La definición de C del tipo va_list se da en la 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]; 

La macro va_start

La macro va_start inicializa la estructura de la siguiente manera:

reg_save_area El elemento apunta al inicio del área de guardar registro.

overflow_arg_area Este puntero se usa para buscar argumentos pasados ​​en la stack. Se inicializa con la dirección del primer argumento pasado en la stack, si existe, y luego siempre se actualiza para apuntar al inicio del siguiente argumento en la stack.

gp_offset El elemento contiene el desplazamiento en bytes desde reg_save_area hasta el lugar donde se guarda el siguiente registro de argumento de propósito general disponible. En caso de que todos los registros de argumentos se hayan agotado, se establece en el valor 48 (6 * 8).

fp_offset El elemento contiene el desplazamiento en bytes desde reg_save_area hasta el lugar donde se guarda el siguiente registro de argumento de coma flotante disponible. En caso de que todos los registros de argumentos se hayan agotado, se establece en el valor 304 (6 * 8 + 16 * 16).

Resultó que el problema era que gcc estaba haciendo va_list un tipo de matriz. Mi función era de la firma:

 void foo(va_list ap); 

y quería pasar un puntero a ap a otra función, así que lo hice:

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

Desafortunadamente, los tipos de matriz decaen a tipos de puntero en las listas de argumentos de función, por lo que en lugar de pasar un puntero a la estructura original, estaba pasando un puntero a un puntero.

Para evitar el problema, cambié el código a:

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

Esta es la única solución portátil que pude encontrar, que tiene en cuenta la posibilidad de que va_list sea ​​un tipo de matriz y la posibilidad de que no lo sea.