1

I'm writing a 64bit operating system using g++, and I have a variadic function like:

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

which shall behave quite like printf. The problem here is that g++ follows the System V ABI, and thus it passes the first arguments in RDI, RSI, RDX, RCX, R8, R9, then pushes remaining (if any) on the stack.

Using the old stdarg.h macros va_start, va_arg, etc, with cdecl, was all quite easy as va_arg just took the next element on the stack. But now those macros won't work at all until the 7th argument.

The only possibile solutions are (IMHO):

  • Forcing g++ to create a cdecl function. This seems impossible as __attribute__((cdecl)) is deliberately and clearly highlighted as ignored.
  • Have a new set of macros that work with the new way of passing arguments.

(I'm actually working on Win, so I don't have the glibc headers to check their implementation).

Anyone with a solution? Thanks in advance.

Francesco Boffa
  • 1,402
  • 1
  • 19
  • 35

1 Answers1

2

stdarg.h is NOT part of libc, it's part of the compiler itself. So if you're using g++ it should have a stdarg.h that comes with it to handle this -- it generally gets installed in gcc's private include directory, which is searched automatically before the system includes.

If you look in gcc's stdarg.h, you see that the va_ macros are all defined to map to __builtin functions that the compiler magically knows how to deal with:

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)

and those builtins all understand the calling conventions that are used by the target ABI.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Also note that the old method (bogus pointer arithmetic) for implementing `stdarg.h` **does not work** on modern GCC versions, even on x86 (32-bit). In case the compiler chooses to inline the function, the arguments will not exist at all on the stack, and even if not, there are other ways it can be broken. The `__builtin` functions really are necessary, unfortunately. – R.. GitHub STOP HELPING ICE Mar 26 '12 at 17:40