Подтвердить что ты не робот

Каков формат структуры va_list x86_64?

У кого-нибудь есть ссылка на представление va_list в ABI x86_64 (тот, который используется в Linux)? Я пытаюсь отладить некоторый код, где стек или аргументы кажутся коррумпированными, и это действительно поможет понять, что я должен видеть...

4b9b3361

Ответ 1

Я сделал свой комментарий в ответ.

Это может помочь. Это ссылка, пусть и легкая.

Ссылка на список аргументов Variable начинается на стр. 50, затем она продолжается, стр. 52-53 документы va_list:

Тип va_list

Тип va_list - это массив содержащий один элемент из одного структура, содержащая необходимые информация для внедрения va_arg макро. Определение C va_list тип приведен на рисунке 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

Макрос va_start инициализирует структуры следующим образом:

reg_save_area Элемент указывает на начало области сохранения регистров.

overflow_arg_area Этот указатель используется для извлечения аргументов, переданных на стек. Он инициализируется адрес первого аргумента, переданного стек, если он есть, а затем всегда обновить, чтобы указать на начало следующий аргумент в стеке.

gp_offset Элемент содержит смещение в байтах от reg_save_area до место, где следующий доступный общий регистр аргументов назначения сохраняется. В все регистры аргументов были исчерпан, он установлен в значение 48 (6 * 8).

fp_offset Элемент содержит смещение в байтах от reg_save_area до место, где следующий доступный регистр точечного аргумента сохраняется. В все регистры аргументов были исчерпан, он установлен в значение 304 (6 * 8 + 16 * 16).

Ответ 2

Оказывается, проблема заключалась в том, что gcc создал va_list тип массива. Моя функция была подписи:

void foo(va_list ap);

и я хотел передать указатель на ap на другую функцию, поэтому я сделал:

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

К сожалению, типы массивов распадаются на типы указателей в списках аргументов функций, поэтому вместо передачи указателя на исходную структуру я передавал указатель на указатель.

Чтобы обойти проблему, я изменил код на:

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

Это единственное портативное решение, которое я мог бы придумать, что объясняет как возможность, что va_list - тип массива, так и возможность того, что это не так.