// File: Alcaro[P]bridges/arlib/file-exepath.cpp
// Function: (anonymous namespace)::exepath_finder::exepath_finder()
exepath_finder()
	{
#ifdef ARTYPE_DLL
		// dladdr() can return this information, but it doesn't always contain path, so better use something else
		
		char linkpath[64];
		strcpy(linkpath, "/proc/self/map_files/");
		
		DIR* dir = opendir(linkpath);
		if (!dir) goto fallback;
		
		dirent* ent;
		while ((ent = readdir(dir)))
		{
			// for . and .., sscanf will fail, return 0, and leave low/high unchanged
			// easiest way to ensure this doesn't break anything is initialize high to 0, and check it before low, so check is false
			uintptr_t low;
			uintptr_t high = 0;
			sscanf(ent->d_name, "%zx-%zx", &low, &high);
			
			uintptr_t target = (uintptr_t)this;
			if (target < high && low <= target)
			{
				strcat(linkpath, ent->d_name);
				break;
			}
		}
		closedir(dir);
		if (!ent)
		{
		fallback: // should be unreachable
			strcpy(linkpath, "/proc/self/exe");
		}
#else
		const char * linkpath = "/proc/self/exe";
#endif
		
		char buf[256];
		
		ssize_t r = readlink(linkpath, buf, sizeof(buf));
		if (r <= 0) return;
		
		if ((size_t)r < sizeof(buf)-1)
		{
			buf[r] = '\0'; // readlink doesn't nul terminate
			fullname = buf;
		}
		else
		{
			size_t buflen = sizeof(buf);
			char* ptr = NULL;
		again:
			buflen *= 2;
			ptr = xrealloc(ptr, buflen);
			
			ssize_t r = readlink(linkpath, ptr, buflen);
			if (r <= 0) return;
			if ((size_t)r >= buflen-1) goto again;
			
			ptr[r] = '\0';
			fullname = string::create_usurp(ptr);
		}
		
		path = file::dirname(fullname);
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x7800
movq -0x198(%rbp), %rdi
addq $0x10, %rdi
callq 0x5f70
leaq 0x52d34(%rip), %rax     # 0x6343a
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
leaq -0x130(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
callq 0x4390
movq %rax, -0x138(%rbp)
cmpq $0x0, -0x138(%rbp)
jg 0x10735
jmp 0x108da
cmpq $0xff, -0x138(%rbp)
jae 0x10779
movq -0x198(%rbp), %rcx
movq -0x138(%rbp), %rax
movb $0x0, -0x130(%rbp,%rax)
leaq -0x130(%rbp), %rax
movq %rcx, -0x18(%rbp)
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x63e0
jmp 0x1087d
movq $0x100, -0x140(%rbp) # imm = 0x100
movq $0x0, -0x148(%rbp)
movq -0x140(%rbp), %rax
shlq %rax
movq %rax, -0x140(%rbp)
movq -0x148(%rbp), %rsi
leaq -0x158(%rbp), %rdi
callq 0x10950
movq -0x140(%rbp), %rsi
movq -0x158(%rbp), %rdi
callq 0x2d690
movq %rax, -0x150(%rbp)
leaq -0x150(%rbp), %rdi
callq 0x10970
movq %rax, -0x148(%rbp)
movq -0x30(%rbp), %rdi
movq -0x148(%rbp), %rsi
movq -0x140(%rbp), %rdx
callq 0x4390
movq %rax, -0x160(%rbp)
cmpq $0x0, -0x160(%rbp)
jg 0x1080d
jmp 0x108da
movq -0x160(%rbp), %rax
movq -0x140(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jb 0x10829
jmp 0x1078f
movq -0x148(%rbp), %rax
movq -0x160(%rbp), %rcx
movb $0x0, (%rax,%rcx)
movq -0x148(%rbp), %rsi
leaq -0x170(%rbp), %rdi
callq 0x37760
movq -0x198(%rbp), %rax
movq %rax, -0x8(%rbp)
leaq -0x170(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x10670
leaq -0x170(%rbp), %rdi
callq 0x5870
movq -0x198(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0x190(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x188(%rbp)
movq -0x190(%rbp), %rdi
movq -0x188(%rbp), %rsi
callq 0x10990
movq %rax, %rcx
movq -0x198(%rbp), %rax
movq %rcx, -0x180(%rbp)
movq %rdx, -0x178(%rbp)
movq -0x180(%rbp), %rcx
movq %rcx, 0x10(%rax)
movq -0x178(%rbp), %rcx
movq %rcx, 0x18(%rax)
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
nopw %cs:(%rax,%rax)