Как заставить cdecl на вариационной функции - PullRequest
1 голос
/ 26 марта 2012

Я пишу 64-битную операционную систему, используя g ++, и у меня есть переменная функция, такая как:

void DbgPrint(const char *fmt, ...);

, который должен вести себя как printf. Проблема здесь в том, что g ++ следует за ABI System V и, таким образом, передает первые аргументы в RDI, RSI, RDX, RCX, R8, R9, а затем помещает оставшиеся (если они есть) в стек.

Использовать старые макросы stdarg.h va_start, va_arg и т. Д. С cdecl было довольно просто, поскольку va_arg просто взял следующий элемент в стеке. Но теперь эти макросы не будут работать до седьмого аргумента.

Единственные возможные решения (ИМХО):

  • Заставить g ++ создать функцию cdecl. Это кажется невозможным, поскольку атрибут __ __ ((cdecl)) сознательно и четко выделен как , игнорируемый .
  • Иметь новый набор макросов, которые работают с новым способом передачи аргументов.

(на самом деле я работаю над Win, поэтому у меня нет заголовков glibc, чтобы проверить их реализацию).

Кто-нибудь с решением? Заранее спасибо.

1 Ответ

2 голосов
/ 26 марта 2012

stdarg.h НЕ является частью libc, это часть самого компилятора. Так что если вы используете g ++, он должен иметь stdarg.h, который поставляется вместе с ним для этого - обычно он устанавливается в частный каталог включения gcc, который ищется автоматически перед включением системы.

Если вы посмотрите в stdarg.h gcc, вы увидите, что все макросы va_ определены для отображения на функции __builtin, с которыми волшебник знает, как иметь дело с компилятором:

typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;

#define va_start(v,l)   __builtin_va_start(v,l)
#define va_end(v)   __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)

и все эти встроенные функции понимают соглашения о вызовах, которые используются целевым ABI.

...