// File: /workspace/github_cpp_makefile_star2_O1/coduin[P]epiphany-bin-info/epiphany-bin-info.cpp
// Function: parseFile(char*, unsigned long)
int parseFile(char* buffer, size_t fsize) {
    Elf32_Ehdr* ehdr = (Elf32_Ehdr*)buffer;
    Elf32_Phdr* phdr;
    Elf32_Shdr* shdr;
    const char* strtab;

    // Array of program headers
    phdr = (Elf32_Phdr*)&buffer[ehdr->e_phoff];
    // Array of section headers
    shdr = (Elf32_Shdr*)&buffer[ehdr->e_shoff];

    // Check if header matches Epiphany signature
    // Check if all section headers point to something within file buffer
    if (fsize < sizeof(Elf32_Ehdr) || !isEpiphanyElf(ehdr) ||
        (ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf32_Phdr) > fsize ||
         (ehdr->e_shoff + ehdr->e_shnum * sizeof(Elf32_Shdr)) > fsize) ||
        (ehdr->e_shstrndx >= ehdr->e_shnum) ||
        ((shdr[ehdr->e_shstrndx].sh_offset + shdr[ehdr->e_shstrndx].sh_size) >
         fsize)) {
        return 1;
    }

    // By the check above, we can be sure that we stay inside the buffer
    parseProgramHeader(phdr, ehdr->e_phnum);

    strtab = &buffer[shdr[ehdr->e_shstrndx].sh_offset];
    parseSections(shdr, ehdr->e_shnum, strtab, shdr[ehdr->e_shstrndx].sh_size);

    for (size_t i = 0; i < ehdr->e_shnum; i++) {
        if (shdr[i].sh_type == SHT_SYMTAB) {
            Elf32_Sym* symbol = (Elf32_Sym*)&buffer[shdr[i].sh_offset];
            size_t count = shdr[i].sh_size / shdr[i].sh_entsize;

            // Check if all symbols are within file buffer
            if (shdr[i].sh_offset + count * sizeof(Elf32_Sym) > fsize)
                return 1;

            // Section with symbol names
            Elf32_Shdr* symstrhdr = &shdr[shdr[i].sh_link];

            // Check if the symbol name table is within file buffer
            if (shdr[i].sh_link >= ehdr->e_shnum)
                return 1;
            if (symstrhdr->sh_offset + symstrhdr->sh_size > fsize)
                return 1;

            const char* symstr = &buffer[symstrhdr->sh_offset];

            parseSymbolTable(symbol, count, symstr, symstrhdr->sh_size);
        }
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl $0x1, %ebp
cmpq $0x34, %rsi
jb 0x31b4
movq %rsi, %rbx
movq %rdi, %r14
movl 0x1c(%rdi), %r12d
movl 0x20(%rdi), %r13d
callq 0x268d
testb %al, %al
je 0x31b4
movzwl 0x2c(%r14), %esi
movl %esi, %eax
shll $0x5, %eax
addq %r12, %rax
cmpq %rbx, %rax
ja 0x31b4
movzwl 0x30(%r14), %eax
leaq (%rax,%rax,4), %rcx
leaq (,%rcx,8), %rcx
addq %r13, %rcx
cmpq %rbx, %rcx
ja 0x31b4
movzwl 0x32(%r14), %ecx
cmpw %ax, %cx
jae 0x31b4
leaq (%r14,%r13), %r15
leaq (%rcx,%rcx,4), %rax
movl 0x14(%r15,%rax,8), %ecx
addl 0x10(%r15,%rax,8), %ecx
cmpq %rbx, %rcx
ja 0x31b4
addq %r14, %r12
movq %r12, %rdi
callq 0x26ba
movzwl 0x32(%r14), %eax
leaq (%rax,%rax,4), %rax
movl 0x10(%r15,%rax,8), %edx
movl 0x14(%r15,%rax,8), %ecx
addq %r14, %rdx
movzwl 0x30(%r14), %esi
movq %r15, %rdi
callq 0x29c2
movzwl 0x30(%r14), %ecx
testw %cx, %cx
setne %sil
je 0x31ad
leaq (%r14,%r13), %r12
addq $0x24, %r12
xorl %r13d, %r13d
cmpl $0x2, -0x20(%r12)
jne 0x3198
movl -0x14(%r12), %edi
movl -0x10(%r12), %eax
xorl %edx, %edx
divl (%r12)
movq %rax, %rdx
shlq $0x4, %rdx
addq %rdi, %rdx
cmpq %rbx, %rdx
ja 0x31ad
movl -0xc(%r12), %edx
movzwl %cx, %ecx
cmpl %ecx, %edx
jae 0x31ad
leaq (%rdx,%rdx,4), %rcx
movl 0x10(%r15,%rcx,8), %edx
movl 0x14(%r15,%rcx,8), %ecx
leal (%rcx,%rdx), %r8d
cmpq %rbx, %r8
ja 0x31ad
addq %r14, %rdi
addq %r14, %rdx
movq %rax, %rsi
callq 0x2b44
incq %r13
movzwl 0x30(%r14), %ecx
addq $0x28, %r12
cmpq %rcx, %r13
setb %sil
jb 0x3140
movzbl %sil, %ebp
andl $0x1, %ebp
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq