// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x110(%rbp)
movq %rdi, %rax
movq %rax, -0x108(%rbp)
movq %rsi, -0x8(%rbp)
xorl %esi, %esi
movl $0x20, %edx
callq 0x6060
movq -0x8(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x6740
cmpl $0x0, %eax
je 0x16ec6
jmp 0x17286
movl -0x80(%rbp), %eax
andl $0xf000, %eax           # imm = 0xF000
cmpl $0x8000, %eax           # imm = 0x8000
je 0x16eda
jmp 0x17286
movq -0x8(%rbp), %rdi
xorl %esi, %esi
movb $0x0, %al
callq 0x67a0
movl %eax, -0x9c(%rbp)
movq -0x68(%rbp), %rsi
movl -0x9c(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x1, %edx
movl $0x2, %ecx
movq %r9, %rdi
callq 0x67b0
movq %rax, -0xa8(%rbp)
movl -0x9c(%rbp), %edi
callq 0x6090
movq $-0x1, %rax
cmpq %rax, -0xa8(%rbp)
jne 0x16f36
jmp 0x17286
movq -0x110(%rbp), %rax
movq -0xa8(%rbp), %rcx
movq %rcx, (%rax)
movq -0x68(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq (%rax), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x7f, %eax
jne 0x16f98
movq -0xb0(%rbp), %rax
movzbl 0x1(%rax), %eax
cmpl $0x45, %eax
jne 0x16f98
movq -0xb0(%rbp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x4c, %eax
jne 0x16f98
movq -0xb0(%rbp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x46, %eax
je 0x16fa9
movq -0x110(%rbp), %rdi
callq 0x172a0
jmp 0x17286
movq -0x110(%rbp), %rax
movq $0x0, -0xb8(%rbp)
movq $0x0, -0xc0(%rbp)
movq (%rax), %rcx
movq -0xb0(%rbp), %rdx
addq 0x28(%rdx), %rcx
movq -0xb0(%rbp), %rdx
movzwl 0x3e(%rdx), %edx
movq -0xb0(%rbp), %rsi
movzwl 0x3a(%rsi), %esi
imull %esi, %edx
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, -0xc8(%rbp)
movq (%rax), %rax
movq -0xc8(%rbp), %rcx
addq 0x18(%rcx), %rax
movq %rax, -0xd0(%rbp)
movq $0x1, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movq -0xb0(%rbp), %rcx
movzwl 0x3c(%rcx), %ecx
cmpq %rcx, %rax
jae 0x17107
movq -0x110(%rbp), %rax
movq (%rax), %rax
movq -0xb0(%rbp), %rcx
addq 0x28(%rcx), %rax
movq -0xd8(%rbp), %rcx
movq -0xb0(%rbp), %rdx
movzwl 0x3a(%rdx), %edx
imulq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
movq -0xd0(%rbp), %rax
movq -0xe0(%rbp), %rcx
movl (%rcx), %ecx
addq %rcx, %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rdi
leaq 0x752e8(%rip), %rsi     # 0x8c37a
callq 0x64e0
cmpl $0x0, %eax
jne 0x170b9
movq -0xe0(%rbp), %rax
cmpl $0xb, 0x4(%rax)
jne 0x170b9
movq -0xe0(%rbp), %rax
movq %rax, -0xb8(%rbp)
jmp 0x170ee
movq -0xe8(%rbp), %rdi
leaq 0x752bb(%rip), %rsi     # 0x8c382
callq 0x64e0
cmpl $0x0, %eax
jne 0x170ec
movq -0xe0(%rbp), %rax
cmpl $0x3, 0x4(%rax)
jne 0x170ec
movq -0xe0(%rbp), %rax
movq %rax, -0xc0(%rbp)
jmp 0x170ee
jmp 0x170f0
movq -0xd8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd8(%rbp)
jmp 0x1701a
cmpq $0x0, -0xb8(%rbp)
je 0x1711b
cmpq $0x0, -0xc0(%rbp)
jne 0x1712c
movq -0x110(%rbp), %rdi
callq 0x172a0
jmp 0x17286
movq -0x110(%rbp), %rax
movq (%rax), %rax
movq -0xc0(%rbp), %rcx
addq 0x18(%rcx), %rax
movq %rax, -0xf0(%rbp)
movq $0x0, -0xf8(%rbp)
movq -0xf8(%rbp), %rax
movq -0xb8(%rbp), %rcx
cmpq 0x20(%rcx), %rax
jae 0x17284
movq -0x110(%rbp), %rax
movq (%rax), %rax
movq -0xb8(%rbp), %rcx
addq 0x18(%rcx), %rax
addq -0xf8(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rax
movzwl 0x6(%rax), %eax
cmpl $0x0, %eax
je 0x17264
movq -0x100(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jbe 0x17264
movq -0x100(%rbp), %rax
movzbl 0x4(%rax), %eax
andl $0xf, %eax
cmpl $0x2, %eax
jne 0x17264
movq -0x110(%rbp), %rax
movq 0x18(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rax)
movq 0x10(%rax), %rdi
imulq $0x18, 0x18(%rax), %rsi
callq 0x66c0
movq -0x110(%rbp), %rdx
movq %rax, 0x10(%rdx)
movq -0xf0(%rbp), %rcx
movq -0x100(%rbp), %rax
movl (%rax), %eax
addq %rax, %rcx
movq 0x10(%rdx), %rax
movq 0x18(%rdx), %rsi
subq $0x1, %rsi
imulq $0x18, %rsi, %rsi
addq %rsi, %rax
movq %rcx, (%rax)
movq -0x100(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x10(%rdx), %rax
movq 0x18(%rdx), %rsi
subq $0x1, %rsi
imulq $0x18, %rsi, %rsi
addq %rsi, %rax
movq %rcx, 0x8(%rax)
movq -0x100(%rbp), %rax
movq 0x10(%rax), %rcx
movq 0x10(%rdx), %rax
movq 0x18(%rdx), %rdx
subq $0x1, %rdx
imulq $0x18, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
jmp 0x17266
movq -0xb8(%rbp), %rax
movq 0x38(%rax), %rax
addq -0xf8(%rbp), %rax
movq %rax, -0xf8(%rbp)
jmp 0x17153
jmp 0x17286
movq -0x108(%rbp), %rax
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nopw %cs:(%rax,%rax)