// File: /workspace/github_c_makefile_star2_O3/arkanis[P]process-map/map.c
// Function: LoadElfSymbols
ElfSymbols LoadElfSymbols(const char* path) {
	ElfSymbols symbols = (ElfSymbols){ 0 };
	struct stat stats;
	if ( stat(path, &stats) != 0 )  // abort if file doesn't exist, e.g. "[heap]"
		return symbols;
	if ( !S_ISREG(stats.st_mode) )  // abort if file isn't a regular file
		return symbols;
	
	int fd = open(path, O_RDONLY);
	void* mmapStart = mmap(NULL, stats.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	close(fd);
	if (mmapStart == MAP_FAILED)
		return symbols;
	
	symbols.elfMmapStart = mmapStart;
	symbols.elfMmapSize = stats.st_size;
	
	Elf64_Ehdr* header = symbols.elfMmapStart;
	if ( !(header->e_ident[0] == ELFMAG0 && header->e_ident[1] == ELFMAG1 && header->e_ident[2] == ELFMAG2 && header->e_ident[3] == ELFMAG3) ) {
		UnloadElfSymbols(&symbols);
		return symbols;
	}
	
	// Search for the .dynsym (dynamic linking symbols) and .dynstr (string table for symbol names) sections
	Elf64_Shdr *dynsym = NULL, *dynstr = NULL;
	Elf64_Shdr* sectionNameStrtab = symbols.elfMmapStart + header->e_shoff + header->e_shstrndx * header->e_shentsize;
	const char* sectionNames = symbols.elfMmapStart + sectionNameStrtab->sh_offset;
	for (size_t i = 1; i < header->e_shnum; i++) {  // Note: Index 0 is reserved, skip it
		Elf64_Shdr* section = symbols.elfMmapStart + header->e_shoff + i * header->e_shentsize;
		const char* sectionName = sectionNames + section->sh_name;
		if ( strcmp(sectionName, ".dynsym") == 0 && section->sh_type == SHT_DYNSYM ) {
			dynsym = section;
		} else if ( strcmp(sectionName, ".dynstr") == 0 && section->sh_type == SHT_STRTAB ) {
			dynstr = section;
		}
	}
	
	if (dynsym == NULL || dynstr == NULL) {
		UnloadElfSymbols(&symbols);
		return symbols;
	}
	
	const char* symbolNames = symbols.elfMmapStart + dynstr->sh_offset;
	for (size_t offset = 0; offset < dynsym->sh_size; offset += dynsym->sh_entsize) {
		Elf64_Sym* symbol = symbols.elfMmapStart + dynsym->sh_offset + offset;
		
		// We're only interested in symbols that are defined in a section of this file (have a shndx) and contain actual code (a size and type STT_FUNC)
		if ( symbol->st_shndx != SHN_UNDEF && symbol->st_size > 0 && ELF64_ST_TYPE(symbol->st_info) == STT_FUNC ) {
			symbols.count++;
			symbols.at = realloc(symbols.at, sizeof(symbols.at[0]) * symbols.count);
			symbols.at[symbols.count - 1].name = symbolNames + symbol->st_name;
			symbols.at[symbols.count - 1].fileOffset = symbol->st_value;  // Looks like symbol offsets are global file offsets
			symbols.at[symbols.count - 1].size = symbol->st_size;
		}
	}
	
	return symbols;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rsi, %r14
movq %rdi, %rbx
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rdi)
movups %xmm0, (%rdi)
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6770
testl %eax, %eax
jne 0x15706
movl $0xf000, %eax           # imm = 0xF000
andl 0x30(%rsp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x15706
movq %r14, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x67d0
movl %eax, %ebp
movq 0x48(%rsp), %r15
xorl %edi, %edi
movq %r15, %rsi
movl $0x1, %edx
movl $0x2, %ecx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x67e0
movq %rax, %r14
movl %ebp, %edi
callq 0x6090
cmpq $-0x1, %r14
je 0x15706
movq %r14, (%rbx)
movq %r15, 0x8(%rbx)
cmpb $0x7f, (%r14)
jne 0x156f1
cmpb $0x45, 0x1(%r14)
jne 0x156f1
cmpb $0x4c, 0x2(%r14)
jne 0x156f1
cmpb $0x46, 0x3(%r14)
jne 0x156f1
movzwl 0x3c(%r14), %r12d
cmpq $0x2, %r12
jb 0x1571b
movq 0x28(%r14), %rbp
leaq (%r14,%rbp), %rax
movzwl 0x3e(%r14), %ecx
movzwl 0x3a(%r14), %edx
imulq %rdx, %rcx
movq 0x18(%rcx,%rax), %r15
addq %r14, %r15
decq %r12
movq %rdx, 0x10(%rsp)
addq %rdx, %rbp
addq %r14, %rbp
movq $0x0, (%rsp)
movq $0x0, 0x8(%rsp)
movl (%rbp), %r13d
addq %r15, %r13
movq %r13, %rdi
leaq 0x4ffe4(%rip), %rsi     # 0x655e2
callq 0x6510
testl %eax, %eax
jne 0x15613
cmpl $0xb, 0x4(%rbp)
jne 0x15613
movq %rbp, (%rsp)
jmp 0x15638
movq %r13, %rdi
leaq 0x4ffcd(%rip), %rsi     # 0x655ea
callq 0x6510
testl %eax, %eax
jne 0x15638
cmpl $0x3, 0x4(%rbp)
movq 0x8(%rsp), %rax
cmoveq %rbp, %rax
movq %rax, 0x8(%rsp)
addq 0x10(%rsp), %rbp
decq %r12
jne 0x155ed
movq (%rsp), %rsi
testq %rsi, %rsi
movq 0x8(%rsp), %rax
je 0x1571b
testq %rax, %rax
je 0x1571b
movq 0x20(%rsi), %rcx
testq %rcx, %rcx
je 0x15706
movq 0x18(%rax), %rax
addq %r14, %rax
movq %rax, 0x10(%rsp)
xorl %eax, %eax
xorl %r13d, %r13d
xorl %ebp, %ebp
movq 0x18(%rsi), %r12
addq %r14, %r12
cmpw $0x0, 0x6(%rbp,%r12)
je 0x156de
cmpq $0x0, 0x10(%r12,%rbp)
je 0x156de
movb 0x4(%r12,%rbp), %dl
andb $0xf, %dl
cmpb $0x2, %dl
jne 0x156de
leaq 0x8(,%r13,8), %rcx
incq %r13
leaq (%rcx,%rcx,2), %r15
movq %rax, %rdi
movq %r15, %rsi
callq 0x66f0
movl (%r12,%rbp), %ecx
addq 0x10(%rsp), %rcx
movq %rcx, -0x18(%rax,%r15)
movups 0x8(%r12,%rbp), %xmm0
movups %xmm0, -0x10(%rax,%r15)
movq (%rsp), %rsi
movq 0x20(%rsi), %rcx
addq 0x38(%rsi), %rbp
cmpq %rcx, %rbp
jb 0x1567d
movq %r13, 0x18(%rbx)
movq %rax, 0x10(%rbx)
jmp 0x15706
movq %r14, %rdi
movq %r15, %rsi
callq 0x65f0
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
movups %xmm0, 0x10(%rbx)
movq %rbx, %rax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x15725
jmp 0x15706