2012-03-26 2 views
1

Я пишу 64bit операционную систему, используя г ++, и у меня есть VARIADIC функции, как:Как заставить Cdecl на VARIADIC функции

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

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

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

только possibile решения (ИМХО):

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

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

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

ответ

2

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

Если вы посмотрите в stdarg.h ССАГПЗ, вы видите, что 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.

+0

Также обратите внимание, что старый метод (арифметика фиктивного указателя) для реализации 'stdarg.h' ** не работает ** на современных версиях GCC, даже на x86 (32-разрядный). В случае, если компилятор выбирает встроенную функцию, аргументы вообще не будут существовать в стеке, и даже если нет, есть другие способы, которыми это может быть нарушено. К сожалению, функции '__builtin' действительно необходимы. –

+0

спасибо, человек, ты был очень полезен :) –