Monday, February 15, 2016

building va_list on x86_64 linux


т.к. va_arg() в clang/gсс это builtin_va_arg
приготовить не так просто, как под windows

можно глянуть пункт 3.5.7 в http://www.x86-64.org/documentation/abi.pdf
также EmitVAArgFromMemory() в clang source code base

Делал так:

struct myvalist {
    int32_t gp_offset;
    int32_t fp_offset;
    int8_t* overflow_arg_area;
    int8_t* reg_save_area;
} ;

template
void push(int8_t * & b, const T & t)
{
    int v = alignof(T);
    if (v > 8)
    {
        b = reinterpret_cast(uint64_t(b + 15) & ~15);
    }
    memcpy(b, &t, sizeof(t));
    b += sizeof(t);
    b = reinterpret_cast(uint64_t(b + 7) & ~7);
}


int main()
{
    va_list ap;
    int8_t buf[1024];
    myvalist * lst = (myvalist*)≈
    lst->gp_offset = 48;
    lst->fp_offset = 304;
    lst->overflow_arg_area = &buf[8];
    lst->reg_save_area = (int8_t*)1;
    int8_t * t = &buf[8];
    push(t, 1);
    push(t, (int)'5');
    push(t, 2.0);
    push(t, 3ULL);
    push(t, t);
    push(t, (const char *)"hello");
    push(t, (const char *)"dragon");
    push(t, 3.22131231);
    push(t, 9.0);
    vfprintf(stdout, "%d %d %f %lld %p %s %s %f %f\n", ap);
    return 0;
}


No comments:

Post a Comment