// File: /workspace/github_c_makefile_star2_O3/melynx[P]peekaboo/libpeekaboo/libpeekaboo.c
// Function: load_memrefs_offsets
void load_memrefs_offsets(char *dir_path, peekaboo_trace_t *trace)
{
	char path[MAX_PATH];
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "memrefs_offsets");

	if (access(path, F_OK) == -1)
	{
		uint64_t base_offset = 0;

		/* KH: This is a ad-hoc patch to fix the bug in peekaboo_dr.
		 * When the application process forks, there are some residues
		 * in memfile buffer that can't be cleaned up.
		 * Thus, When read those traces, we need to find the real starting
		 * point of the memfile. We use base_offset to store it.
		 */
		if (trace->internal->version >= 3)
		{
			// Find the first instruction that has memory access
			uint64_t first_pc = 0x0;
			size_t trace_len = trace->internal->num_insns;
			size_t id=1;
			for(; id<=trace_len; id++)
			{
				size_t num_mem = get_num_mem(id, trace);
				if (num_mem == 0) continue;
				first_pc = get_addr(id, trace);
				break;
			}
			if (id > trace_len)
			{
				// A weird trace. It doesn't have any memory access. 
				// Do nothing but gives a warning.
				fprintf(stderr, "libpeekaboo: [Warning] No memory ops found in this trace.\n");
			}
			else
			{
				if (first_pc==0) PEEKABOO_DIE("libpeekaboo: zero pc for id %lu", id);
				fseek(trace->memfile, 0, SEEK_END);
				memfile_t mem;
				mem.pc = 0;
				errno = 0;
				fseek(trace->memfile, base_offset, SEEK_SET);
				size_t read_size = fread(&mem, sizeof(memfile_t), 1, trace->memfile);
				while(mem.pc!=first_pc && errno==0)
				{
					base_offset += sizeof(memfile_t);
					fseek(trace->memfile, base_offset, SEEK_SET);
					read_size = fread(&mem, sizeof(memfile_t), 1, trace->memfile);
				}
			}
		}
		if (base_offset!=0) fprintf(stderr, "libpeekaboo: (Trace from a child thread/process?) Re-align the memory offset, starting from %ld.\n", base_offset/sizeof(memfile_t));

		FILE *memrefs_offsets = fopen(path, "wb");
		if (!memrefs_offsets) PEEKABOO_DIE("libpeekaboo: Fail to open memref file!\n");

		memref_t buffer[1024];
		size_t write_buffer[1024];

		size_t read_size = 0;
		size_t offset = base_offset;

		rewind(trace->memrefs);
		do {
			read_size = fread(buffer, sizeof(memref_t), 1024, trace->memrefs);
			int x;
			for (x=0; x<read_size; x++)
			{
				if (buffer[x].length)
				{
					write_buffer[x] = offset;
					if (trace->internal->version < 3)
						// Memfiles in old versions are different
						offset += buffer[x].length * sizeof(uint64_t) * 3;
					else
						offset += buffer[x].length * sizeof(memfile_t);
				}
				else
				{
					write_buffer[x] = -1;
				}
			}
			fwrite(write_buffer, sizeof(size_t), read_size, memrefs_offsets);
		} while (read_size == 1024);
		rewind(trace->memrefs);
		fclose(memrefs_offsets);
	}
	trace->memrefs_offsets = fopen(path, "rb");

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3108, %rsp           # imm = 0x3108
movq %rsi, %rbx
movq %rdi, %rcx
leaq 0x2346(%rip), %rdx      # 0x5fca
leaq 0x2345(%rip), %r8       # 0x5fd0
movq %rsp, %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
xorl %eax, %eax
callq 0x3150
movq %r14, %rdi
xorl %esi, %esi
callq 0x3240
cmpl $-0x1, %eax
jne 0x3e91
movq 0x38(%rbx), %rax
cmpl $0x3, 0x58(%rax)
jb 0x3daa
movq 0x28(%rax), %r15
testq %r15, %r15
je 0x3ce5
movl $0x1, %r14d
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3050
testq %rax, %rax
jne 0x3cef
incq %r14
cmpq %r15, %r14
jbe 0x3ccd
callq 0x3377
jmp 0x3daa
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3220
testq %rax, %rax
je 0x3ec8
movq %rax, %r15
movq 0x20(%rbx), %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x3230
leaq 0x100(%rsp), %r14
movq $0x0, 0x18(%r14)
callq 0x3090
movq %rax, %r12
movl $0x0, (%rax)
movq 0x20(%rbx), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x3230
movq 0x20(%rbx), %rcx
movl $0x20, %esi
movl $0x1, %edx
movq %r14, %rdi
callq 0x30d0
cmpq %r15, 0x18(%r14)
je 0x3daa
xorl %r14d, %r14d
leaq 0x100(%rsp), %r13
cmpl $0x0, (%r12)
jne 0x3da1
addq $0x20, %r14
movq 0x20(%rbx), %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x3230
movq 0x20(%rbx), %rcx
movl $0x20, %esi
movl $0x1, %edx
movq %r13, %rdi
callq 0x30d0
cmpq %r15, 0x118(%rsp)
jne 0x3d68
testq %r14, %r14
jne 0x3eb6
xorl %r14d, %r14d
leaq 0x2134(%rip), %rsi      # 0x5ee8
movq %rsp, %rdi
callq 0x3260
testq %rax, %rax
je 0x3ec3
movq %rax, %r15
movq 0x18(%rbx), %rdi
callq 0x3140
leaq 0x2100(%rsp), %r12
leaq 0x100(%rsp), %r13
movq 0x18(%rbx), %rcx
movl $0x4, %esi
movl $0x400, %edx            # imm = 0x400
movq %r12, %rdi
callq 0x30d0
movq %rax, %rbp
testq %rax, %rax
je 0x3e68
xorl %eax, %eax
movl 0x2100(%rsp,%rax,4), %ecx
testq %rcx, %rcx
je 0x3e29
movq %r14, 0x100(%rsp,%rax,8)
movq 0x38(%rbx), %rdx
cmpl $0x2, 0x58(%rdx)
ja 0x3e37
leaq (%rcx,%rcx,2), %rcx
leaq (%r14,%rcx,8), %r14
jmp 0x3e3e
movq $-0x1, 0x100(%rsp,%rax,8)
jmp 0x3e3e
shlq $0x5, %rcx
addq %rcx, %r14
incq %rax
cmpq %rax, %rbp
jne 0x3e01
movl $0x8, %esi
movq %r13, %rdi
movq %rbp, %rdx
movq %r15, %rcx
callq 0x3280
cmpq $0x400, %rbp            # imm = 0x400
je 0x3de1
jmp 0x3e80
leaq 0x100(%rsp), %rdi
movl $0x8, %esi
movq %rbp, %rdx
movq %r15, %rcx
callq 0x3280
movq 0x18(%rbx), %rdi
callq 0x3140
movq %r15, %rdi
callq 0x30f0
leaq 0x222d(%rip), %rsi      # 0x60c5
movq %rsp, %rdi
callq 0x3260
movq %rax, 0x30(%rbx)
addq $0x3108, %rsp           # imm = 0x3108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
callq 0x3334
jmp 0x3dad
callq 0x3393
movq %r14, %rdi
callq 0x3353