# Invocation: gdb -x gdb-extract-def

# extract-state /path/to/foo.bin /path/to/foo.fixture
define extract-state
  file $arg0

  # Disables logging to stdout - only log to file
  set logging redirect on

  set logging file $arg1
  set logging overwrite on
  set logging on

  run

  printf "---BEGIN JSON---\n"
  printf "[\n"
  printf "    %d,\n", $eax
  printf "    %d,\n", $ecx
  printf "    %d,\n", $edx
  printf "    %d,\n", $ebx
  printf "    %d,\n", $esp
  printf "    %d,\n", $ebp
  printf "    %d,\n", $esi
  printf "    %d,\n", $edi
  printf "\n"

  printf "    %d,\n", $eip
  printf "\n"

  # For fpu registers, check the tag register first. If the tag index is
  # invalid and you try to access to corresponding register, gdb exits with an
  # error.
  set $top = $fstat >> 11 & 7
  if ($ftag >> (2 * (($top + 0) & 7)) & 3) != 2
    printf "    %.100e,\n", $st0
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 1) & 7)) & 3) != 2
    printf "    %.100e,\n", $st1
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 2) & 7)) & 3) != 2
    printf "    %.100e,\n", $st2
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 3) & 7)) & 3) != 2
    printf "    %.100e,\n", $st3
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 4) & 7)) & 3) != 2
    printf "    %.100e,\n", $st4
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 5) & 7)) & 3) != 2
    printf "    %.100e,\n", $st5
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 6) & 7)) & 3) != 2
    printf "    %.100e,\n", $st6
  else
    printf "    \"invalid\",\n"
  end
  if ($ftag >> (2 * (($top + 7) & 7)) & 3) != 2
    printf "    %.100e,\n", $st7
  else
    printf "    \"invalid\",\n"
  end
  printf "\n"

  printf "    %d,\n", $mm0.v2_int32[0]
  printf "    %d,\n", $mm0.v2_int32[1]
  printf "    %d,\n", $mm1.v2_int32[0]
  printf "    %d,\n", $mm1.v2_int32[1]
  printf "    %d,\n", $mm2.v2_int32[0]
  printf "    %d,\n", $mm2.v2_int32[1]
  printf "    %d,\n", $mm3.v2_int32[0]
  printf "    %d,\n", $mm3.v2_int32[1]
  printf "    %d,\n", $mm4.v2_int32[0]
  printf "    %d,\n", $mm4.v2_int32[1]
  printf "    %d,\n", $mm5.v2_int32[0]
  printf "    %d,\n", $mm5.v2_int32[1]
  printf "    %d,\n", $mm6.v2_int32[0]
  printf "    %d,\n", $mm6.v2_int32[1]
  printf "    %d,\n", $mm7.v2_int32[0]
  printf "    %d,\n", $mm7.v2_int32[1]
  printf "\n"

  printf "    %d,\n", $xmm0.v4_int32[0]
  printf "    %d,\n", $xmm0.v4_int32[1]
  printf "    %d,\n", $xmm0.v4_int32[2]
  printf "    %d,\n", $xmm0.v4_int32[3]
  printf "    %d,\n", $xmm1.v4_int32[0]
  printf "    %d,\n", $xmm1.v4_int32[1]
  printf "    %d,\n", $xmm1.v4_int32[2]
  printf "    %d,\n", $xmm1.v4_int32[3]
  printf "    %d,\n", $xmm2.v4_int32[0]
  printf "    %d,\n", $xmm2.v4_int32[1]
  printf "    %d,\n", $xmm2.v4_int32[2]
  printf "    %d,\n", $xmm2.v4_int32[3]
  printf "    %d,\n", $xmm3.v4_int32[0]
  printf "    %d,\n", $xmm3.v4_int32[1]
  printf "    %d,\n", $xmm3.v4_int32[2]
  printf "    %d,\n", $xmm3.v4_int32[3]
  printf "    %d,\n", $xmm4.v4_int32[0]
  printf "    %d,\n", $xmm4.v4_int32[1]
  printf "    %d,\n", $xmm4.v4_int32[2]
  printf "    %d,\n", $xmm4.v4_int32[3]
  printf "    %d,\n", $xmm5.v4_int32[0]
  printf "    %d,\n", $xmm5.v4_int32[1]
  printf "    %d,\n", $xmm5.v4_int32[2]
  printf "    %d,\n", $xmm5.v4_int32[3]
  printf "    %d,\n", $xmm6.v4_int32[0]
  printf "    %d,\n", $xmm6.v4_int32[1]
  printf "    %d,\n", $xmm6.v4_int32[2]
  printf "    %d,\n", $xmm6.v4_int32[3]
  printf "    %d,\n", $xmm7.v4_int32[0]
  printf "    %d,\n", $xmm7.v4_int32[1]
  printf "    %d,\n", $xmm7.v4_int32[2]
  printf "    %d,\n", $xmm7.v4_int32[3]
  printf "\n"


  set $addr=0x100000
  while($addr < 0x102000)
     printf "    %d, %d, %d, %d, %d, %d, %d, %d,\n", *(int*)($addr+0), *(int*)($addr+4), *(int*)($addr+8), *(int*)($addr+12), *(int*)($addr+16), *(int*)($addr+20), *(int*)($addr+24), *(int*)($addr+28)
     set $addr=$addr+32
  end
  printf "\n"

  printf "    %d,\n", $eflags
  printf "    %d,\n", $ftag
  printf "    %d\n", $fstat

  printf "]\n"
  printf "---END JSON---\n"

  set logging off

end
