// File: /workspace/github_c_makefile_star2_O2/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 $0xb8, %rsp
movq %rsi, %r14
movq %rdi, %rbx
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rdi)
movups %xmm0, (%rdi)
leaq 0x28(%rsp), %rsi
movq %r14, %rdi
callq 0x6780
testl %eax, %eax
jne 0x11a7a
movl $0xf000, %eax           # imm = 0xF000
andl 0x40(%rsp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x11a7a
movq %r14, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x67f0
movl %eax, %ebp
movq 0x58(%rsp), %r15
pushq $0x1
popq %rdx
pushq $0x2
popq %rcx
xorl %edi, %edi
movq %r15, %rsi
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x6800
movq %rax, %r14
movl %ebp, %edi
callq 0x6090
cmpq $-0x1, %r14
je 0x11a7a
movq %r14, (%rbx)
movq %r15, 0x8(%rbx)
cmpb $0x7f, (%r14)
jne 0x11a72
cmpb $0x45, 0x1(%r14)
jne 0x11a72
cmpb $0x4c, 0x2(%r14)
jne 0x11a72
cmpb $0x46, 0x3(%r14)
jne 0x11a72
movq 0x28(%r14), %rbp
leaq (%r14,%rbp), %rax
movzwl 0x3e(%r14), %ecx
movzwl 0x3a(%r14), %edx
imulq %rdx, %rcx
movq 0x18(%rcx,%rax), %rax
addq %r14, %rax
movq %rax, 0x20(%rsp)
movzwl 0x3c(%r14), %eax
movq %rax, 0x18(%rsp)
movq %rdx, 0x10(%rsp)
addq %rdx, %rbp
addq %r14, %rbp
pushq $0x1
popq %r15
movq $0x0, 0x8(%rsp)
xorl %r12d, %r12d
cmpq 0x18(%rsp), %r15
jae 0x119d9
movl (%rbp), %r13d
addq 0x20(%rsp), %r13
movq %r13, %rdi
leaq 0x47c54(%rip), %rsi     # 0x595ea
callq 0x6520
testl %eax, %eax
jne 0x119aa
cmpl $0xb, 0x4(%rbp)
jne 0x119aa
movq %rbp, %r12
jmp 0x119cf
movq %r13, %rdi
leaq 0x47c3e(%rip), %rsi     # 0x595f2
callq 0x6520
testl %eax, %eax
jne 0x119cf
cmpl $0x3, 0x4(%rbp)
movq 0x8(%rsp), %rax
cmoveq %rbp, %rax
movq %rax, 0x8(%rsp)
incq %r15
addq 0x10(%rsp), %rbp
jmp 0x1197c
testq %r12, %r12
movq 0x8(%rsp), %rax
je 0x11a72
testq %rax, %rax
je 0x11a72
movq 0x18(%rax), %rax
addq %r14, %rax
movq %rax, 0x10(%rsp)
xorl %eax, %eax
xorl %edx, %edx
xorl %r13d, %r13d
cmpq 0x20(%r12), %r13
jae 0x11a8f
movq 0x18(%r12), %rbp
addq %r14, %rbp
cmpw $0x0, 0x6(%r13,%rbp)
je 0x11a6b
cmpq $0x0, 0x10(%rbp,%r13)
je 0x11a6b
movb 0x4(%rbp,%r13), %cl
andb $0xf, %cl
cmpb $0x2, %cl
jne 0x11a6b
incq %rdx
movq %rdx, 0x18(%rsp)
imulq $0x18, %rdx, %r15
movq %rax, %rdi
movq %r15, %rsi
callq 0x6700
movq 0x18(%rsp), %rdx
movl (%rbp,%r13), %ecx
addq 0x10(%rsp), %rcx
movq %rcx, -0x18(%rax,%r15)
movups 0x8(%rbp,%r13), %xmm0
movups %xmm0, -0x10(%rax,%r15)
addq 0x38(%r12), %r13
jmp 0x11a03
movq %rbx, %rdi
callq 0x11a99
movq %rbx, %rax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rdx, 0x18(%rbx)
movq %rax, 0x10(%rbx)
jmp 0x11a7a