// File: /workspace/github_c_makefile_star2_O1/mikecat[P]x86_interpreter/read_pe.c
// Function: read_pe
int read_pe(uint32_t* eip_value, uint32_t* stack_size, pe_import_params* import_params, const char* filename) {
	size_t filesize = 0;
	uint8_t* filedata = read_whole_file(&filesize, filename);
	uint32_t newheader_offset;
	uint8_t* newheader;
	uint32_t num_section, optheader_size, section_table_size;
	uint8_t* optheader;
	uint32_t magic, entrypoint, image_base, stack_reserve;
	uint8_t* section_table;
	uint32_t i;
	if (filedata == 0) return 0;
	if (filesize < 64) {
		fprintf(stderr, "file size too small for PE header\n");
		free(filedata); return 0;
	}
	if (filedata[0] != 'M' || filedata[1] != 'Z') {
		fprintf(stderr, "not PE file\n");
		free(filedata); return 0;
	}
	newheader_offset = read_num(filedata + 60, 4);
	if (newheader_offset > filesize - 24) {
		fprintf(stderr, "file size too small for PE new header\n");
		free(filedata); return 0;
	}
	newheader = filedata + newheader_offset;
	if (newheader[0] != 'P' || newheader[1] != 'E' || newheader[2] != 0x00 || newheader[3] != 0x00) {
		fprintf(stderr, "wrong PE new header signature\n");
		free(filedata); return 0;
	}
	num_section = read_num(newheader + 6, 2);
	optheader_size = read_num(newheader + 20, 2);
	section_table_size = 40 * num_section;
	if (optheader_size > filesize || filesize - optheader_size < newheader_offset + 24) {
		fprintf(stderr, "file size too small for PE optional header\n");
		free(filedata); return 0;
	}
	if (optheader_size < 76) { /* TODO */
		fprintf(stderr, "PE optional header too small\n");
		free(filedata); return 0;
	}
	optheader = newheader + 24;
	magic = read_num(optheader + 0, 2);
	entrypoint = read_num(optheader + 16, 4);
	image_base = read_num(optheader + 28, 4);
	stack_reserve = read_num(optheader + 72, 4);
	if (magic == 0x20b) {
		fprintf(stderr, "unsupported 64-bit PE file detected\n");
		free(filedata); return 0;
	}
	if (UINT32_MAX - image_base < entrypoint) {
		fprintf(stderr, "PE entrypoint out of address space\n");
		free(filedata); return 0;
	}
	if (import_params != NULL) {
		uint32_t import_addr, import_size, iat_addr, iat_size;
		if (optheader_size >= 112) {
			import_addr = read_num(optheader + 104, 4);
			import_size = read_num(optheader + 108, 4);
		} else {
			import_addr = 0;
			import_size = 0;
		}
		if (optheader_size >= 200) {
			iat_addr = read_num(optheader + 192, 4);
			iat_size = read_num(optheader + 196, 4);
		} else {
			iat_addr = 0;
			iat_size = 0;
		}
		if (import_size > 0) {
			if (UINT32_MAX - image_base < import_addr ||
			UINT32_MAX - (image_base + import_addr) < import_size - 1) {
				fprintf(stderr, "PE import informaton out of address space\n");
				free(filedata); return 0;
			}
		}
		if (iat_size > 0) {
			if (UINT32_MAX - image_base < iat_addr ||
			UINT32_MAX - (image_base + iat_addr) < iat_size - 1) {
				fprintf(stderr, "PE import address table out of address space\n");
				free(filedata); return 0;
			}
		}
		import_params->image_base = image_base;
		import_params->import_addr = image_base + import_addr;
		import_params->import_size = import_size;
		import_params->iat_addr = image_base + iat_addr;
		import_params->iat_size = iat_size;
	}
	if (section_table_size > filesize || filesize - section_table_size < newheader_offset + 24 + optheader_size) {
		fprintf(stderr, "file size too small for PE section table\n");
		free(filedata); return 0;
	}
	section_table = optheader + optheader_size;
	for (i = 0; i < num_section; i++) {
		uint8_t* section_data = section_table + 40 * i;
		uint32_t size, addr, file_size, file_offset;
		uint32_t load_size;
		size = read_num(section_data + 8, 4);
		addr = read_num(section_data + 12, 4);
		file_size = read_num(section_data + 16, 4);
		file_offset = read_num(section_data + 20, 4);
		load_size = (file_offset == 0 ? 0 : (size < file_size ? size : file_size));
		if (UINT32_MAX - image_base < addr || (size > 0 && UINT32_MAX - (image_base + addr) < size - 1)) {
			fprintf(stderr, "PE section %"PRIu32" out of address space\n", i);
			free(filedata); return 0;
		}
		if (filesize - file_offset < load_size) {
			fprintf(stderr, "PE section %"PRIu32" out of file\n", i);
			free(filedata); return 0;
		}
		dmemory_allocate(image_base + addr, size);
		dmemory_write(filedata + file_offset, image_base + addr, load_size);
	}
	if (eip_value != NULL) *eip_value = image_base + entrypoint;
	if (stack_size != NULL) *stack_size = stack_reserve;
	free(filedata);
	return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, %r12
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x30(%rsp), %rdi
movq $0x0, (%rdi)
movq %rcx, %rsi
callq 0xa868
testq %rax, %rax
je 0xb1ce
movq %rax, %r13
movq 0x30(%rsp), %rax
cmpq $0x3f, %rax
jbe 0xb1e7
cmpb $0x4d, (%r13)
jne 0xb1d9
cmpb $0x5a, 0x1(%r13)
jne 0xb1d9
leaq 0x3c(%r13), %rsi
xorl %ecx, %ecx
xorl %edx, %edx
movzbl (%rsi), %edi
shll %cl, %edi
orl %edi, %edx
addq $0x8, %rcx
incq %rsi
cmpq $0x20, %rcx
jne 0xad98
leaq -0x18(%rax), %rcx
cmpq %rdx, %rcx
jb 0xb1ee
cmpb $0x50, (%r13,%rdx)
jne 0xb1d2
leaq (%rdx,%r13), %rsi
cmpb $0x45, 0x1(%rsi)
jne 0xb1d2
cmpb $0x0, 0x2(%rsi)
jne 0xb1d2
cmpb $0x0, 0x3(%rsi)
jne 0xb1d2
leaq 0x6(%rsi), %r8
xorl %ecx, %ecx
xorl %edi, %edi
movzbl (%r8), %r9d
shll %cl, %r9d
orl %r9d, %edi
addq $0x8, %rcx
incq %r8
cmpq $0x10, %rcx
jne 0xadef
leaq 0x14(%rsi), %r9
xorl %ecx, %ecx
xorl %r8d, %r8d
movzbl (%r9), %r10d
shll %cl, %r10d
orl %r10d, %r8d
addq $0x8, %rcx
incq %r9
cmpq $0x10, %rcx
jne 0xae0f
movl %r8d, %ebp
movq %rax, %rcx
subq %rbp, %rcx
jb 0xb1e0
addl $0x18, %edx
cmpq %rdx, %rcx
jb 0xb1e0
cmpl $0x4b, %r8d
jbe 0xb1fc
movq %rbx, 0x40(%rsp)
leal (,%rdi,8), %ecx
leal (%rcx,%rcx,4), %ecx
movl %ecx, 0x18(%rsp)
leaq 0x18(%rsi), %rbx
xorl %ecx, %ecx
xorl %r11d, %r11d
movzbl (%rbx), %r10d
shll %cl, %r10d
orl %r10d, %r11d
addq $0x8, %rcx
incq %rbx
cmpq $0x10, %rcx
jne 0xae67
leaq 0x28(%rsi), %rbx
xorl %ecx, %ecx
xorl %r9d, %r9d
movzbl (%rbx), %r10d
shll %cl, %r10d
orl %r10d, %r9d
addq $0x8, %rcx
incq %rbx
cmpq $0x20, %rcx
jne 0xae87
movq %r14, 0x38(%rsp)
leaq 0x34(%rsi), %r14
xorl %ecx, %ecx
xorl %ebx, %ebx
movzbl (%r14), %r10d
shll %cl, %r10d
orl %r10d, %ebx
addq $0x8, %rcx
incq %r14
cmpq $0x20, %rcx
jne 0xaeab
leaq 0x60(%rsi), %r14
xorl %ecx, %ecx
xorl %r15d, %r15d
movzbl (%r14), %r10d
shll %cl, %r10d
orl %r10d, %r15d
addq $0x8, %rcx
incq %r14
cmpq $0x20, %rcx
jne 0xaecb
cmpl $0x20b, %r11d           # imm = 0x20B
je 0xb203
movl %ebx, %ecx
notl %ecx
movl %ecx, 0x14(%rsp)
cmpl %ecx, %r9d
ja 0xb20a
movq %r13, 0x8(%rsp)
testq %r12, %r12
movl %r9d, 0x2c(%rsp)
je 0xb030
movq %rbp, 0x20(%rsp)
xorl %ebp, %ebp
movl $0x0, %r14d
movl $0x0, %r11d
cmpl $0x70, %r8d
jb 0xaf73
leaq 0x80(%rsi), %r14
xorl %ecx, %ecx
xorl %r11d, %r11d
movzbl (%r14), %r10d
shll %cl, %r10d
orl %r10d, %r11d
addq $0x8, %rcx
incq %r14
cmpq $0x20, %rcx
jne 0xaf38
leaq 0x84(%rsi), %r13
xorl %ecx, %ecx
xorl %r14d, %r14d
movzbl (%r13), %r10d
shll %cl, %r10d
orl %r10d, %r14d
addq $0x8, %rcx
incq %r13
cmpq $0x20, %rcx
jne 0xaf5b
movl $0x0, %r13d
cmpl $0xc8, %r8d
jb 0xafc8
leaq 0xd8(%rsi), %rbp
xorl %ecx, %ecx
xorl %r13d, %r13d
movzbl (%rbp), %r10d
shll %cl, %r10d
orl %r10d, %r13d
addq $0x8, %rcx
incq %rbp
cmpq $0x20, %rcx
jne 0xaf8e
leaq 0xdc(%rsi), %r10
xorl %ecx, %ecx
xorl %ebp, %ebp
movzbl (%r10), %r9d
shll %cl, %r9d
orl %r9d, %ebp
addq $0x8, %rcx
incq %r10
cmpq $0x20, %rcx
jne 0xafb1
testl %r14d, %r14d
je 0xafeb
cmpl 0x14(%rsp), %r11d
ja 0xb23d
leal (%r11,%rbx), %ecx
movl %r14d, %r9d
negl %r9d
cmpl %r9d, %ecx
ja 0xb23d
testl %ebp, %ebp
je 0xb00d
cmpl 0x14(%rsp), %r13d
ja 0xb244
leal (%rbx,%r13), %ecx
movl %ebp, %r9d
negl %r9d
cmpl %r9d, %ecx
ja 0xb244
movl %ebx, (%r12)
addl %ebx, %r11d
movl %r11d, 0x4(%r12)
movl %r14d, 0x8(%r12)
addl %ebx, %r13d
movl %r13d, 0xc(%r12)
movl %ebp, 0x10(%r12)
movq 0x20(%rsp), %rbp
movl 0x18(%rsp), %ecx
subq %rcx, %rax
jb 0xb1f5
addl %edx, %r8d
cmpq %r8, %rax
jb 0xb1f5
movq %rbx, 0x18(%rsp)
testl %edi, %edi
je 0xb1a0
movl %edi, %eax
movq %rax, 0x48(%rsp)
leaq (%rsi,%rbp), %rax
addq $0x20, %rax
movq %rax, 0x20(%rsp)
leaq 0x24(%rbp,%rsi), %rax
movq %rax, 0x60(%rsp)
leaq 0x28(%rbp,%rsi), %rax
movq %rax, 0x58(%rsp)
leaq (%rsi,%rbp), %rax
addq $0x2c, %rax
movq %rax, 0x50(%rsp)
xorl %ebx, %ebx
xorl %edx, %edx
movl %ebx, %r8d
andl $-0x8, %r8d
movq 0x50(%rsp), %rax
addq %r8, %rax
movq 0x58(%rsp), %rcx
leaq (%rcx,%r8), %r10
movq 0x60(%rsp), %rcx
leaq (%rcx,%r8), %rdi
addq 0x20(%rsp), %r8
xorl %ecx, %ecx
xorl %esi, %esi
movzbl (%r8), %r9d
shll %cl, %r9d
orl %r9d, %esi
addq $0x8, %rcx
incq %r8
cmpq $0x20, %rcx
jne 0xb0b9
xorl %ecx, %ecx
xorl %r13d, %r13d
movq 0x18(%rsp), %r9
movzbl (%rdi), %r8d
shll %cl, %r8d
orl %r8d, %r13d
addq $0x8, %rcx
incq %rdi
cmpq $0x20, %rcx
jne 0xb0da
xorl %ecx, %ecx
xorl %ebp, %ebp
movzbl (%r10), %edi
shll %cl, %edi
orl %edi, %ebp
addq $0x8, %rcx
incq %r10
cmpq $0x20, %rcx
jne 0xb0f5
xorl %ecx, %ecx
xorl %r8d, %r8d
movzbl (%rax), %edi
shll %cl, %edi
orl %edi, %r8d
addq $0x8, %rcx
incq %rax
cmpq $0x20, %rcx
jne 0xb10f
cmpl %ebp, %esi
cmovbl %esi, %ebp
testl %r8d, %r8d
cmovel %r8d, %ebp
cmpl 0x14(%rsp), %r13d
ja 0xb22a
testl %esi, %esi
je 0xb14f
leal (%r9,%r13), %eax
movl %esi, %ecx
negl %ecx
cmpl %ecx, %eax
ja 0xb22a
movq 0x30(%rsp), %rax
movl %r8d, %r14d
subq %r14, %rax
movl %ebp, %ecx
cmpq %rcx, %rax
jb 0xb24d
addl %r9d, %r13d
movl %r13d, %edi
movl %r15d, %r12d
movq %rdx, %r15
callq 0x6edb
addq 0x8(%rsp), %r14
movq %r14, %rdi
movl %r13d, %esi
movl %ebp, %edx
callq 0x6d8a
movq %r15, %rdx
movl %r12d, %r15d
incq %rdx
addq $0x28, %rbx
cmpq 0x48(%rsp), %rdx
jne 0xb08f
movq 0x38(%rsp), %rax
testq %rax, %rax
je 0xb1b5
movq 0x18(%rsp), %rcx
addl 0x2c(%rsp), %ecx
movl %ecx, (%rax)
movl $0x1, %ebp
movq 0x40(%rsp), %rax
testq %rax, %rax
movq 0x8(%rsp), %r13
je 0xb211
movl %r15d, (%rax)
jmp 0xb211
xorl %ebp, %ebp
jmp 0xb219
callq 0x1a1e
jmp 0xb20f
callq 0x19fc
jmp 0xb20f
callq 0x1b0c
jmp 0xb20f
callq 0x1b50
jmp 0xb20f
callq 0x1b2e
jmp 0xb20f
callq 0x1a84
jmp 0xb249
callq 0x1aea
jmp 0xb20f
callq 0x1ac8
jmp 0xb20f
callq 0x1aa6
xorl %ebp, %ebp
movq %r13, %rdi
callq 0x1030
movl %ebp, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x7dc7(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x30e9(%rip), %rsi      # 0xe324
jmp 0xb25e
callq 0x1a40
jmp 0xb249
callq 0x1a62
xorl %ebp, %ebp
jmp 0xb267
movq 0x7da4(%rip), %rax      # 0x12ff8
movq (%rax), %rdi
leaq 0x30ea(%rip), %rsi      # 0xe348
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x10d0
movq 0x8(%rsp), %r13
jmp 0xb211
nop