// File: /workspace/github_c_makefile_star2_O2/mikeakohn[P]print_pe/build/../src/optional_header.c
// Function: optional_header_read
int optional_header_read(
  struct optional_header_t *optional_header,
  FILE *in,
  int header_size)
{
  int t;

  long marker = ftell(in);

  optional_header->Magic = read_uint16(in);
  optional_header->MajorLinkerVersion = getc(in);
  optional_header->MinorLinkerVersion = getc(in);
  optional_header->SizeOfCode = read_uint32(in);
  optional_header->SizeOfInitializedData = read_uint32(in);
  optional_header->SizeOfUninitializedData = read_uint32(in);
  optional_header->AddressOfEntryPoint = read_uint32(in);
  optional_header->BaseOfCode = read_uint32(in);

  int bitsize = 32;

  if (optional_header->Magic != 0x20b)
  {
    optional_header->BaseOfData = read_uint32(in);
  }
    else
  {
    bitsize = 64;
  }

  // FIXME: header_size for PE32 is 28, PE32+ is 24.  Is this really
  //        needed anyway?
  if (header_size <= 28) { return 0; }

  if (bitsize == 32)
  {
    optional_header->ImageBase = read_uint32(in);
  }
    else
  {
    optional_header->ImageBase = read_uint64(in);
  }

  optional_header->SectionAlignment = read_uint32(in);
  optional_header->FileAlignment = read_uint32(in);
  optional_header->MajorOperatingSystemVersion = read_uint16(in);
  optional_header->MinorOperatingSystemVersion = read_uint16(in);
  optional_header->MajorImageVersion = read_uint16(in);
  optional_header->MinorImageVersion = read_uint16(in);
  optional_header->MajorSubsystemVersion = read_uint16(in);
  optional_header->MinorSubsystemVersion = read_uint16(in);
  optional_header->Reserved1 = read_uint32(in);
  optional_header->SizeOfImage = read_uint32(in);
  optional_header->SizeOfHeaders = read_uint32(in);
  optional_header->CheckSum = read_uint32(in);
  optional_header->Subsystem = read_uint16(in);
  optional_header->DllCharacteristics = read_uint16(in);

  if (bitsize == 32)
  {
    optional_header->SizeOfStackReserve = read_uint32(in);
    optional_header->SizeOfStackCommit = read_uint32(in);
    optional_header->SizeOfHeapReserve = read_uint32(in);
    optional_header->SizeOfHeapCommit = read_uint32(in);
  }
    else
  {
    optional_header->SizeOfStackReserve = read_uint64(in);
    optional_header->SizeOfStackCommit = read_uint64(in);
    optional_header->SizeOfHeapReserve = read_uint64(in);
    optional_header->SizeOfHeapCommit = read_uint64(in);
  }

  optional_header->LoaderFlags = read_uint32(in);
  optional_header->NumberOfRvaAndSizes = read_uint32(in);

  int used_length = (int)(ftell(in) - marker);

  if (header_size > used_length)
  {
    optional_header->DataDirectoryCount = (header_size - used_length) / 8;

    for (t = 0; t < optional_header->DataDirectoryCount; t++)
    {
      optional_header->directory_entry[t].virtual_address = read_uint32(in);
      optional_header->directory_entry[t].size = read_uint32(in);
    }
  }

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
movq %rsi, %rdi
callq 0x30f0
movq %rax, %r15
movq %rbx, %rdi
callq 0x5168
movw %ax, (%r14)
movq %rbx, %rdi
callq 0x3160
movb %al, 0x2(%r14)
movq %rbx, %rdi
callq 0x3160
movb %al, 0x3(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x4(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x8(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0xc(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x10(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x14(%r14)
movzwl (%r14), %r12d
cmpw $0x20b, %r12w           # imm = 0x20B
jne 0x574e
cmpl $0x1d, %ebp
jl 0x58ef
movq %rbx, %rdi
callq 0x508c
jmp 0x576d
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x18(%r14)
cmpl $0x1d, %ebp
jl 0x58ef
movq %rbx, %rdi
callq 0x5126
cltq
movq %rax, 0x20(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x28(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x2c(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x30(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x32(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x34(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x36(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x38(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x3a(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x3c(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x40(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x44(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x48(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x4c(%r14)
movq %rbx, %rdi
callq 0x5168
movw %ax, 0x4e(%r14)
movq %rbx, %rdi
cmpw $0x20b, %r12w           # imm = 0x20B
jne 0x5857
callq 0x508c
movq %rax, 0x50(%r14)
movq %rbx, %rdi
callq 0x508c
movq %rax, 0x58(%r14)
movq %rbx, %rdi
callq 0x508c
movq %rax, 0x60(%r14)
movq %rbx, %rdi
callq 0x508c
jmp 0x5888
callq 0x5126
cltq
movq %rax, 0x50(%r14)
movq %rbx, %rdi
callq 0x5126
cltq
movq %rax, 0x58(%r14)
movq %rbx, %rdi
callq 0x5126
cltq
movq %rax, 0x60(%r14)
movq %rbx, %rdi
callq 0x5126
cltq
movq %rax, 0x68(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x70(%r14)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x74(%r14)
movq %rbx, %rdi
callq 0x30f0
subl %r15d, %eax
subl %eax, %ebp
jle 0x58ef
pushq $0x8
popq %rcx
movl %ebp, %eax
cltd
idivl %ecx
movl %eax, 0x78(%r14)
xorl %r15d, %r15d
cltq
cmpq %rax, %r15
jge 0x58ef
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x7c(%r14,%r15,8)
movq %rbx, %rdi
callq 0x5126
movl %eax, 0x80(%r14,%r15,8)
incq %r15
movl 0x78(%r14), %eax
jmp 0x58c2
xorl %eax, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq