Обычно я делаю это, просто выгружая содержимое стека, используя команду dd esp
(для x86) или dq rsp
(для x64).Зная начальный адрес va_list, немного легче найти место в стеке, где начинается блок vararg, но обычно вы можете либо угадать его, либо рассчитать, зная размеры регулярных (не vararg параметров) функции.
Вот аннотированный пример для x86.Вызываемая функция:
printf("%d %o %g %s %c", 101, 201, 301.0, "401-string", '5');
в отладчике:
0:000> bp MSVCR100D!printf
0:000> g
Breakpoint 1 hit
eax=00000001 ebx=00000000 ecx=2549afc4 edx=00000000 esi=002ceeb8 edi=002cf040
eip=0ff57ee0 esp=002cee98 ebp=002cf04c iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
MSVCR100D!printf:
0ff57ee0 8bff mov edi,edi
0:000> dd /c1 esp
002cee98 01365cee // return address
002cee9c 0137d6e8 // pointer to the format string "%d %o %g %s %c" --> next follows our variable arguments
002ceea0 00000065 // first vararg argument, int 101
002ceea4 000000c9 // second vararg argument, int 201
002ceea8 00000000 // third vararg argument, double 301.0, it occupies two slots in stack
002ceeac 4072d000 // third argument continues
002ceeb0 0137d70c // fourth vararg argument, pointer to string
002ceeb4 00000035 // fifth vararg argument, 8-bit character (still occupies 4 bytes in stack)
002ceeb8 25b87244
002ceebc 002cf254
002ceec0 0041c520
002ceec4 00000000
...
Для других функций это будет очень похоже, потому что все функции, использующие переменное число аргументов, должны следовать за вызовом __cdeclсоглашение, так что вы найдете тот же тип размещения параметров в стеке.