diff --git a/arch/x86_64.S b/arch/x86_64.S index 60a7c04..d8f805e 100644 --- a/arch/x86_64.S +++ b/arch/x86_64.S @@ -6,6 +6,8 @@ .globl _cu_memset .globl cu_memzero .globl cu_memtest +.globl cu_va_start +.globl cu_va_arg .text @@ -113,4 +115,42 @@ cu_memtest: ret .testfail: mov %rsi, %rax - ret \ No newline at end of file + ret + + +cu_va_start: + // RDI - va + mov %rsp, %rax + mov %rdi, %rsp + add $0x30, %rsp + + push %r9 + push %r8 + push %rcx + push %rdx + push %rsi + push %rdi + + mov %rax, %rsp + ret + +cu_va_arg: + // RDI - va, RSI - index + push %rbx + mov %rsi, %rbx + shl $3, %rbx + + cmp $6, %rsi + jge .va_stack + + mov (%rbx,%rdi),%rax + + pop %rbx + ret +.va_stack: + sub $0x30, %rbx + add $0x10, %rbx + mov (%rbx,%rbp),%rax + + pop %rbx + ret diff --git a/test.c b/test.c index d84b7dd..cf41c9b 100644 --- a/test.c +++ b/test.c @@ -8,6 +8,7 @@ #include "bitmap.h" #include "endian.h" #include "struct.h" +#include "va_list.h" typedef uint8_t item_t[14]; @@ -35,6 +36,16 @@ CU_VALUE_INT64() CU_VALUE_ARRAY_ZERO(sizeof(char)) CU_STRUCT_END() +void va_test(int fixed, ...) +{ + cu_va_list va; + cu_va_start(&va); + + printf("va_test\n"); + for (unsigned i = 0; i < 6; i++) + printf("\t%lu\n", cu_va_arg(&va, i)); +} + int main() { cutil_init(); @@ -147,6 +158,9 @@ int main() printf("value_offset\t%u\n", value_offset(CU_STRUCT(test_s), 5, &test)); printf("value_size\t%u\n", value_size(CU_STRUCT(test_s), 5, &test)); + printf("[va_list]\n"); + va_test(1337, 1, 2, 3, 4, 5); + cutil_exit(); return 0; -} \ No newline at end of file +} diff --git a/va_list.h b/va_list.h new file mode 100644 index 0000000..a5c1db1 --- /dev/null +++ b/va_list.h @@ -0,0 +1,19 @@ +#ifndef __VA_LIST_H +#define __VA_LIST_H + +#include "cutypes.h" + +#if (CU_ARCH == x86_64) +# define VA_NUM 6 +#else +# define VA_NUM 0 +#endif + +typedef struct { + uword args[VA_NUM]; +} cu_va_list; + +extern void cu_va_start(cu_va_list* va); +extern uword cu_va_arg(cu_va_list* va, unsigned idx); + +#endif \ No newline at end of file