// File: /workspace/github_c_makefile_star2_O0/hobo0xcc[P]rve/src/elf.c
// Function: LoadElf
uint64_t LoadElf(State *state, size_t size, uint8_t *bin) {
    Elf64_Ehdr *ehdr = (Elf64_Ehdr *)bin;

    if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
        Error("Not an ELF file");
    } else if (ehdr->e_type != ET_EXEC) {
        Error("Not an executable ELF file");
    }

    uint64_t sh_size = sizeof(Elf64_Shdr);
    Elf64_Shdr *shstrtab =
        (Elf64_Shdr *)(bin + ehdr->e_shoff + (sh_size * ehdr->e_shstrndx));

    char *strtab = (char *)(bin + shstrtab->sh_offset);

    uint64_t text_addr;
    bool tohost;
    for (uint64_t i = 0; i < sh_size * ehdr->e_shnum; i += sh_size) {
        Elf64_Shdr *shdr = (Elf64_Shdr *)(bin + ehdr->e_shoff + i);
        if (shdr->sh_type == SHT_PROGBITS) {
            uint64_t virtual_addr = shdr->sh_addr;
            if (virtual_addr == 0)
                continue;

            uint8_t *text = (uint8_t *)(bin + shdr->sh_offset);
            size_t text_size = shdr->sh_size;
            char *name = (strtab + shdr->sh_name);
            printf("%s: 0x%llx\n", name, virtual_addr);
            if (!strcmp(name, ".text")) {
                text_addr = virtual_addr;
            }

            LoadBinaryIntoMemory(state, text, text_size, virtual_addr - DRAM_BASE);
        }
    }

    return ehdr->e_entry;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %eax
subl $0x464c457f, %eax       # imm = 0x464C457F
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0xd525
leaq 0x21e1(%rip), %rdi      # 0xf6fd
movb $0x0, %al
callq 0xd690
jmp 0xd542
movq -0x20(%rbp), %rax
movzwl 0x10(%rax), %eax
cmpl $0x2, %eax
je 0xd540
leaq 0x21d4(%rip), %rdi      # 0xf70d
movb $0x0, %al
callq 0xd690
jmp 0xd542
movq $0x40, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq -0x20(%rbp), %rcx
addq 0x28(%rcx), %rax
movq -0x28(%rbp), %rcx
movq -0x20(%rbp), %rdx
movzwl 0x3e(%rdx), %edx
imulq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
addq 0x18(%rcx), %rax
movq %rax, -0x38(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq -0x28(%rbp), %rcx
movq -0x20(%rbp), %rdx
movzwl 0x3c(%rdx), %edx
imulq %rdx, %rcx
cmpq %rcx, %rax
jae 0xd671
movq -0x18(%rbp), %rax
movq -0x20(%rbp), %rcx
addq 0x28(%rcx), %rax
addq -0x50(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpl $0x1, 0x4(%rax)
jne 0xd65e
movq -0x58(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
jne 0xd5dc
jmp 0xd660
movq -0x18(%rbp), %rax
movq -0x58(%rbp), %rcx
addq 0x18(%rcx), %rax
movq %rax, -0x68(%rbp)
movq -0x58(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x38(%rbp), %rax
movq -0x58(%rbp), %rcx
movl (%rcx), %ecx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rsi
movq -0x60(%rbp), %rdx
leaq 0x2110(%rip), %rdi      # 0xf728
movb $0x0, %al
callq 0x10a0
movq -0x78(%rbp), %rdi
leaq 0x210a(%rip), %rsi      # 0xf734
callq 0x10f0
cmpl $0x0, %eax
jne 0xd63c
movq -0x60(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x68(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq -0x60(%rbp), %rcx
movabsq $0x80000000, %rax       # imm = 0x80000000
subq %rax, %rcx
callq 0xd9b0
jmp 0xd660
movq -0x28(%rbp), %rax
addq -0x50(%rbp), %rax
movq %rax, -0x50(%rbp)
jmp 0xd585
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)