// File: /workspace/github_c_makefile_star2_O0/mikeakohn[P]print_pe/build/../src/print_minidump.c
// Function: main
int main(int argc, char *argv[])
{
  FILE *in;
  const char *filename = NULL;
  struct minidump_header_t minidump_header;
  struct minidump_dir_t minidump_dir;
  struct memory_print_t memory_print = { 0 };
  uint32_t n, i;
  uint32_t cpu_arch = 0;

  memory_print.word_size = 1;

  printf("\nprint_minidump (January 11, 2022) - MiniDump Crash Analyzer\n");
  printf("Copyright 2005-2022 - Michael Kohn  http://www.mikekohn.net/\n\n");

  for (n = 1; n < argc; n++)
  {
    if (argv[n][0] == '-')
    {
      if (strcmp(argv[n], "-start") == 0)
      {
        memory_print.start = strtoll(argv[++n], NULL, 0);
      }
        else
      if (strcmp(argv[n], "-end") == 0)
      {
        memory_print.end = strtoll(argv[++n], NULL, 0);
      }
        else
      if (strcmp(argv[n], "-count") == 0)
      {
        memory_print.count = strtoll(argv[++n], NULL, 0);
      }
        else
      if (strcmp(argv[n], "-word_size") == 0)
      {
        memory_print.word_size = atoi(argv[++n]);

        switch (memory_print.word_size)
        {
          case 8:  memory_print.word_size = 1; break;
          case 16: memory_print.word_size = 2; break;
          case 32: memory_print.word_size = 4; break;
          case 64: memory_print.word_size = 8; break;
          default:
            printf("Error: Unknown word size %d\n", memory_print.word_size);
            exit(1);
        }
      }
        else
      {
        printf("Error: Unknown option %s\n", argv[n]);
        exit(1);
      }
    }
      else
    {
      filename = argv[n];
    }
  }

  if (filename == NULL)
  {
    printf("Usage: print_pe [options] <input file>\n");
    printf("  -start <address>        (starting memory address to dump)\n");
    printf("  -end <address>          (ending memory address to dump)\n");
    printf("  -count <count>          (length of region to dump)\n");
    printf("  -word_size <8/16/32/64> (word size of data to dump)\n");
    exit(0);
  }

  in = fopen(filename, "rb");

  if (in == NULL)
  {
    printf("Could not open input file %s for reading.\n", argv[1]);
    exit(1);
  }

  read_minidump_header(&minidump_header, in);
  print_minidump_header(&minidump_header);

  // Need to find cpu_arch in order to parse ThreadContext.
  fseek(in, minidump_header.ofs_streams, SEEK_SET);
  for (i = 0; i < minidump_header.num_streams; i++)
  {
    read_minidump_dir(&minidump_dir, in);

    if (minidump_dir.stream_type == STREAM_SYSTEM_INFO)
    {
      long marker = ftell(in);
      fseek(in, minidump_dir.ofs_data, SEEK_SET);

      cpu_arch = read_uint16(in);

      fseek(in, marker, SEEK_SET);
    }
  }

  fseek(in, minidump_header.ofs_streams, SEEK_SET);

  for (i = 0; i < minidump_header.num_streams; i++)
  {
    read_minidump_dir(&minidump_dir, in);
    print_minidump_dir(&minidump_dir, i);

    long marker = ftell(in);
    fseek(in, minidump_dir.ofs_data, SEEK_SET);

    switch (minidump_dir.stream_type)
    {
      case STREAM_THREAD_LIST:
        print_minidump_thread_list(in, cpu_arch);
        break;
      case STREAM_MODULE_LIST:
        print_minidump_module_list(in);
        break;
      case STREAM_MEMORY_LIST:
        print_minidump_memory_list(in);
        break;
      case STREAM_MEMORY_INFO_LIST:
        print_minidump_memory_info_list(in);
        break;
      case STREAM_EXCEPTION:
        print_minidump_exception(in);
        break;
      case STREAM_SYSTEM_INFO:
        print_minidump_system_info(in);
        break;
      case STREAM_MEMORY64_LIST:
        print_minidump_memory64_list(in, &memory_print);
        break;
      case STREAM_HANDLE_DATA:
        print_minidump_handle_data(in);
        break;
      case STREAM_MISC_INFO:
        print_minidump_misc_info(in);
        break;
      case STREAM_THREAD_INFO_LIST:
        print_minidump_thread_info_list(in);
        break;
      default:
        break;
    }

    fseek(in, marker, SEEK_SET);
  }

  printf("\n");

  if (memory_print.start != 0)
  {
    if (memory_print.file_offset == 0)
    {
      printf("Error: Memory region 0x%" PRIx64 " doesn't exist.\n",
        memory_print.start);
    }
      else
    {
      printf("Found 0x%" PRIx64 " in range 0x%" PRIx64 "-0x%" PRIx64 "\n",
        memory_print.start,
        memory_print.region_start,
        memory_print.region_end);

      if (memory_print.end == 0)
      {
        memory_print.end = memory_print.start + memory_print.word_size;
      }

      uint64_t length = memory_print.end - memory_print.start;
      uint64_t address = memory_print.start;
      uint64_t i;
      int modulo = 1;

      if (memory_print.count != 0)
      {
        length = memory_print.count;
      }

      switch (memory_print.word_size)
      {
        case 1: modulo = 16; break;
        case 2: modulo = 8;  break;
        case 4: modulo = 4;  break;
        case 8: modulo = 1;  break;
      }

      fseek(in, memory_print.file_offset, SEEK_SET);

      for (i = 0; i < length; i += memory_print.word_size)
      {
        if ((i % modulo) == 0)
        {
          printf("\n%08" PRIx64 ":", address);
        }

        switch (memory_print.word_size)
        {
          case 1: printf(" %02x",  (uint8_t)read_uint8(in)); break;
          case 2: printf(" %04x",  read_uint16(in)); break;
          case 4: printf(" %08x",  read_uint32(in)); break;
          case 8: printf(" %016" PRIx64 , read_uint64(in)); break;
        }

        address += memory_print.word_size;
      }

      printf("\n\n");
    }
  }

  fclose(in);

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x20(%rbp)
leaq -0x88(%rbp), %rdi
xorl %esi, %esi
movl $0x38, %edx
callq 0x1060
movl $0x0, -0x94(%rbp)
movb $0x1, -0x58(%rbp)
leaq 0x2e37(%rip), %rdi      # 0x4080
movb $0x0, %al
callq 0x1050
leaq 0x2e67(%rip), %rdi      # 0x40be
movb $0x0, %al
callq 0x1050
movl $0x1, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpl -0x8(%rbp), %eax
jae 0x147a
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x1452
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
leaq 0x2e57(%rip), %rsi      # 0x40fd
callq 0x1070
cmpl $0x0, %eax
jne 0x12dd
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x8c(%rbp)
movl %ecx, %ecx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x1080
movq %rax, -0x80(%rbp)
jmp 0x1450
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
leaq 0x2e12(%rip), %rsi      # 0x4104
callq 0x1070
cmpl $0x0, %eax
jne 0x1329
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x8c(%rbp)
movl %ecx, %ecx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x1080
movq %rax, -0x78(%rbp)
jmp 0x144e
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
leaq 0x2dcb(%rip), %rsi      # 0x4109
callq 0x1070
cmpl $0x0, %eax
jne 0x1375
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x8c(%rbp)
movl %ecx, %ecx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x1080
movq %rax, -0x70(%rbp)
jmp 0x144c
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
leaq 0x2d86(%rip), %rsi      # 0x4110
callq 0x1070
cmpl $0x0, %eax
jne 0x1424
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
incl %ecx
movl %ecx, -0x8c(%rbp)
movq (%rax,%rcx,8), %rdi
callq 0x10d0
movb %al, -0x58(%rbp)
movzbl -0x58(%rbp), %eax
movl %eax, -0xc8(%rbp)
subl $0x8, %eax
je 0x13ee
jmp 0x13c7
movl -0xc8(%rbp), %eax
subl $0x10, %eax
je 0x13f4
jmp 0x13d4
movl -0xc8(%rbp), %eax
subl $0x20, %eax
je 0x13fa
jmp 0x13e1
movl -0xc8(%rbp), %eax
subl $0x40, %eax
je 0x1400
jmp 0x1406
movb $0x1, -0x58(%rbp)
jmp 0x1422
movb $0x2, -0x58(%rbp)
jmp 0x1422
movb $0x4, -0x58(%rbp)
jmp 0x1422
movb $0x8, -0x58(%rbp)
jmp 0x1422
movzbl -0x58(%rbp), %esi
leaq 0x2d0a(%rip), %rdi      # 0x411b
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x10e0
jmp 0x144a
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rsi
leaq 0x2cff(%rip), %rdi      # 0x4138
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x10e0
jmp 0x144c
jmp 0x144e
jmp 0x1450
jmp 0x1464
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x20(%rbp)
jmp 0x1466
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x1268
cmpq $0x0, -0x20(%rbp)
jne 0x14ce
leaq 0x2cca(%rip), %rdi      # 0x4152
movb $0x0, %al
callq 0x1050
leaq 0x2ce4(%rip), %rdi      # 0x417a
movb $0x0, %al
callq 0x1050
leaq 0x2d13(%rip), %rdi      # 0x41b7
movb $0x0, %al
callq 0x1050
leaq 0x2d40(%rip), %rdi      # 0x41f2
movb $0x0, %al
callq 0x1050
leaq 0x2d68(%rip), %rdi      # 0x4228
movb $0x0, %al
callq 0x1050
xorl %edi, %edi
callq 0x10e0
movq -0x20(%rbp), %rdi
leaq 0x2d86(%rip), %rsi      # 0x425f
callq 0x10c0
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x1509
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x2d6a(%rip), %rdi      # 0x4262
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x10e0
movq -0x18(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x1dc0
leaq -0x40(%rbp), %rdi
callq 0x1f00
movq -0x18(%rbp), %rdi
movl -0x34(%rbp), %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x10b0
movl $0x0, -0x90(%rbp)
movl -0x90(%rbp), %eax
cmpl -0x38(%rbp), %eax
jae 0x15ab
movq -0x18(%rbp), %rsi
leaq -0x4c(%rbp), %rdi
callq 0x1e70
cmpl $0x7, -0x4c(%rbp)
jne 0x1598
movq -0x18(%rbp), %rdi
callq 0x1090
movq %rax, -0xa0(%rbp)
movq -0x18(%rbp), %rdi
movl -0x44(%rbp), %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x10b0
movq -0x18(%rbp), %rdi
callq 0x1a60
movl %eax, -0x94(%rbp)
movq -0x18(%rbp), %rdi
movq -0xa0(%rbp), %rsi
xorl %edx, %edx
callq 0x10b0
jmp 0x159a
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x1539
movq -0x18(%rbp), %rdi
movl -0x34(%rbp), %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x10b0
movl $0x0, -0x90(%rbp)
movl -0x90(%rbp), %eax
cmpl -0x38(%rbp), %eax
jae 0x16ec
movq -0x18(%rbp), %rsi
leaq -0x4c(%rbp), %rdi
movq %rdi, -0xd8(%rbp)
callq 0x1e70
movq -0xd8(%rbp), %rdi
movl -0x90(%rbp), %esi
callq 0x1fd0
movq -0x18(%rbp), %rdi
callq 0x1090
movq %rax, -0xa8(%rbp)
movq -0x18(%rbp), %rdi
movl -0x44(%rbp), %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x10b0
movl -0x4c(%rbp), %eax
addl $-0x3, %eax
movl %eax, %ecx
movq %rcx, -0xd0(%rbp)
subl $0xe, %eax
ja 0x16c4
movq -0xd0(%rbp), %rax
leaq 0x2a04(%rip), %rcx      # 0x4044
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rdi
movl -0x94(%rbp), %esi
callq 0x2050
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2260
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2610
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x26a0
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2890
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2a00
jmp 0x16c6
movq -0x18(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x2bf0
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2d20
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x2f30
jmp 0x16c6
movq -0x18(%rbp), %rdi
callq 0x3070
jmp 0x16c6
jmp 0x16c6
movq -0x18(%rbp), %rdi
movq -0xa8(%rbp), %rsi
xorl %edx, %edx
callq 0x10b0
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x15c5
leaq 0x2a08(%rip), %rdi      # 0x40fb
movb $0x0, %al
callq 0x1050
cmpq $0x0, -0x80(%rbp)
je 0x1918
cmpq $0x0, -0x88(%rbp)
jne 0x1726
movq -0x80(%rbp), %rsi
leaq 0x2b73(%rip), %rdi      # 0x428d
movb $0x0, %al
callq 0x1050
jmp 0x1916
movq -0x80(%rbp), %rsi
movq -0x68(%rbp), %rdx
movq -0x60(%rbp), %rcx
leaq 0x2b7f(%rip), %rdi      # 0x42b8
movb $0x0, %al
callq 0x1050
cmpq $0x0, -0x78(%rbp)
jne 0x1756
movq -0x80(%rbp), %rax
movzbl -0x58(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0xb8(%rbp)
movl $0x1, -0xc4(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x178c
movq -0x70(%rbp), %rax
movq %rax, -0xb0(%rbp)
movzbl -0x58(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0xe0(%rbp)
subl $0x7, %eax
ja 0x17e5
movq -0xe0(%rbp), %rax
leaq 0x2856(%rip), %rcx      # 0x4004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x10, -0xc4(%rbp)
jmp 0x17e5
movl $0x8, -0xc4(%rbp)
jmp 0x17e5
movl $0x4, -0xc4(%rbp)
jmp 0x17e5
movl $0x1, -0xc4(%rbp)
movq -0x18(%rbp), %rdi
movq -0x88(%rbp), %rsi
xorl %edx, %edx
callq 0x10b0
movq $0x0, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
cmpq -0xb0(%rbp), %rax
jae 0x1908
movq -0xc0(%rbp), %rax
movslq -0xc4(%rbp), %rcx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x1844
movq -0xb8(%rbp), %rsi
leaq 0x2a9d(%rip), %rdi      # 0x42da
movb $0x0, %al
callq 0x1050
movzbl -0x58(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0xe8(%rbp)
subl $0x7, %eax
ja 0x18df
movq -0xe8(%rbp), %rax
leaq 0x27ba(%rip), %rcx      # 0x4024
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rdi
callq 0x1aa0
movzbl %al, %esi
leaq 0x2a5c(%rip), %rdi      # 0x42e2
movb $0x0, %al
callq 0x1050
jmp 0x18df
movq -0x18(%rbp), %rdi
callq 0x1a60
movl %eax, %esi
leaq 0x2a47(%rip), %rdi      # 0x42e8
movb $0x0, %al
callq 0x1050
jmp 0x18df
movq -0x18(%rbp), %rdi
callq 0x1a00
movl %eax, %esi
leaq 0x2a32(%rip), %rdi      # 0x42ee
movb $0x0, %al
callq 0x1050
jmp 0x18df
movq -0x18(%rbp), %rdi
callq 0x1930
movq %rax, %rsi
leaq 0x2a1c(%rip), %rdi      # 0x42f4
movb $0x0, %al
callq 0x1050
movzbl -0x58(%rbp), %eax
addq -0xb8(%rbp), %rax
movq %rax, -0xb8(%rbp)
movzbl -0x58(%rbp), %eax
addq -0xc0(%rbp), %rax
movq %rax, -0xc0(%rbp)
jmp 0x1802
leaq 0x27eb(%rip), %rdi      # 0x40fa
movb $0x0, %al
callq 0x1050
jmp 0x1918
movq -0x18(%rbp), %rdi
callq 0x1040
xorl %eax, %eax
addq $0xf0, %rsp
popq %rbp
retq
nopl (%rax)