// File: /workspace/github_cpp_makefile_star2_O2/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
pushq $0x1
popq %rbp
cmpq $0x34, %rsi
jb 0x2d8c
movq %rsi, %rbx
movq %rdi, %r14
movl 0x1c(%rdi), %r12d
movl 0x20(%rdi), %r13d
callq 0x25be
testb %al, %al
je 0x2d8c
movzwl 0x2c(%r14), %esi
movl %esi, %eax
shll $0x5, %eax
addq %r12, %rax
cmpq %rbx, %rax
ja 0x2d8c
movzwl 0x30(%r14), %eax
imulq $0x28, %rax, %rcx
addq %r13, %rcx
cmpq %rbx, %rcx
ja 0x2d8c
movzwl 0x32(%r14), %ecx
cmpw %ax, %cx
jae 0x2d8c
leaq (%r14,%r13), %r15
imulq $0x28, %rcx, %rax
movl 0x14(%r15,%rax), %ecx
addl 0x10(%r15,%rax), %ecx
cmpq %rbx, %rcx
ja 0x2d8c
addq %r14, %r12
movq %r12, %rdi
callq 0x25eb
movzwl 0x32(%r14), %eax
imulq $0x28, %rax, %rax
movl 0x10(%r15,%rax), %edx
movl 0x14(%r15,%rax), %ecx
addq %r14, %rdx
movzwl 0x30(%r14), %esi
movq %r15, %rdi
callq 0x27fa
addq %r14, %r13
addq $0x24, %r13
xorl %r12d, %r12d
movzwl 0x30(%r14), %esi
cmpq %rsi, %r12
jae 0x2d83
cmpl $0x2, -0x20(%r13)
jne 0x2d7a
movl -0x14(%r13), %edi
movl -0x10(%r13), %eax
xorl %edx, %edx
divl (%r13)
movq %rax, %rcx
shlq $0x4, %rcx
addq %rdi, %rcx
cmpq %rbx, %rcx
ja 0x2d83
movl -0xc(%r13), %ecx
cmpl %esi, %ecx
jae 0x2d83
imulq $0x28, %rcx, %rcx
movl 0x10(%r15,%rcx), %edx
movl 0x14(%r15,%rcx), %ecx
leal (%rcx,%rdx), %r8d
cmpq %rbx, %r8
ja 0x2d83
addq %r14, %rdi
addq %r14, %rdx
movq %rax, %rsi
callq 0x28fc
incq %r12
addq $0x28, %r13
jmp 0x2d1f
xorl %ebp, %ebp
cmpq %rsi, %r12
setb %bpl
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq