Qual é o formato da estrutura x86_64 va_list?

Alguém tem uma referência para a representação de va_list na ABI x86_64 (aquela usada no Linux)? Eu estou tentando depurar algum código onde a pilha ou os argumentos parecem corruptos e realmente ajudaria a entender o que eu deveria estar vendo …

Eu fiz o meu comentário em uma resposta.

Isso pode ajudar . É uma referência, ainda que leve.

A referência da Lista de Argumentos Variáveis ​​começa na página 50 e, em seguida, continua, página 52-53 documentos va_list :

O tipo va_list

O tipo va_list é uma matriz contendo um único elemento de uma estrutura contendo as informações necessárias para implementar a macro va_arg. A definição C do tipo va_list é dada na 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]; 

A macro va_start

A macro va_start inicializa a estrutura da seguinte maneira:

reg_save_area O elemento aponta para o início da área de salvamento do registro.

overflow_arg_area Esse ponteiro é usado para buscar argumentos passados ​​na pilha. Ele é inicializado com o endereço do primeiro argumento transmitido na pilha, se houver, e sempre atualizado para apontar para o início do próximo argumento na pilha.

gp_offset O elemento mantém o deslocamento em bytes de reg_save_area para o local onde o próximo registro de argumento de propósito geral disponível é salvo. No caso de todos os registros de argumentos terem sido esgotados, é ajustado para o valor 48 (6 ∗ 8).

fp_offset O elemento mantém o deslocamento em bytes de reg_save_area para o local onde o próximo registro de argumento de ponto flutuante disponível é salvo. No caso de todos os registros de argumentos terem sido esgotados, ele é configurado para o valor 304 (6 ∗ 8 + 16 ∗ 16).

Acontece que o problema é que o gcc está fazendo o va_list um tipo de matriz. Minha function era da assinatura:

 void foo(va_list ap); 

e eu queria passar um ponteiro para ap para outra function, então eu fiz:

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

Infelizmente, tipos de matriz decaem para tipos de ponteiro em listas de argumentos de function, portanto, em vez de passar um ponteiro para a estrutura original, eu estava passando um ponteiro para um ponteiro.

Para contornar o problema, alterei o código para:

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

Esta é a única solução portátil que eu consegui criar, que explica tanto a possibilidade de que va_list seja um tipo de matriz quanto a possibilidade de não ser.

Intereting Posts