// File: /workspace/github_c_makefile_star2_O2/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 0x25e3(%rip), %rdx      # 0x5fca
leaq 0x25e2(%rip), %r8       # 0x5fd0
movq %rsp, %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
xorl %eax, %eax
callq 0x3160
movq %r14, %rdi
xorl %esi, %esi
callq 0x3250
cmpl $-0x1, %eax
jne 0x3b8f
movq 0x38(%rbx), %rax
cmpl $0x3, 0x58(%rax)
jb 0x3ad3
pushq $0x1
popq %r14
movq 0x28(%rax), %r15
cmpq %r15, %r14
ja 0x3bb4
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3050
testq %rax, %rax
jne 0x3a47
incq %r14
jmp 0x3a29
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3230
testq %rax, %rax
je 0x3c17
movq %rax, %r15
movq 0x20(%rbx), %rdi
xorl %r14d, %r14d
pushq $0x2
popq %rdx
xorl %esi, %esi
callq 0x3240
leaq 0x100(%rsp), %rax
andq $0x0, 0x18(%rax)
callq 0x3090
movq %rax, %r13
andl $0x0, (%rax)
pushq $0x20
popq %rbp
pushq $0x1
popq %r12
movq 0x20(%rbx), %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x3240
movq 0x20(%rbx), %rcx
leaq 0x100(%rsp), %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x30e0
cmpq %r15, 0x118(%rsp)
je 0x3aca
cmpl $0x0, (%r13)
jne 0x3aca
addq $0x20, %r14
jmp 0x3a8e
testq %r14, %r14
jne 0x3bd5
xorl %r14d, %r14d
leaq 0x240b(%rip), %rsi      # 0x5ee8
movq %rsp, %rdi
callq 0x3270
testq %rax, %rax
je 0x3bf9
movq %rax, %r15
movq 0x18(%rbx), %rdi
callq 0x3150
leaq 0x100(%rsp), %rbp
pushq $0x8
popq %r12
movq 0x18(%rbx), %rcx
movl $0x400, %edx            # imm = 0x400
leaq 0x2100(%rsp), %rdi
pushq $0x4
popq %rsi
callq 0x30e0
movq %rax, %r13
xorl %eax, %eax
cmpq %rax, %r13
je 0x3b64
movl 0x2100(%rsp,%rax,4), %ecx
testq %rcx, %rcx
je 0x3b4d
movq %r14, 0x100(%rsp,%rax,8)
movq 0x38(%rbx), %rdx
cmpl $0x2, 0x58(%rdx)
ja 0x3b58
imulq $0x18, %rcx, %rcx
jmp 0x3b5c
orq $-0x1, 0x100(%rsp,%rax,8)
jmp 0x3b5f
shlq $0x5, %rcx
addq %rcx, %r14
incq %rax
jmp 0x3b24
movq %rbp, %rdi
movq %r12, %rsi
movq %r13, %rdx
movq %r15, %rcx
callq 0x3290
cmpq $0x400, %r13            # imm = 0x400
je 0x3b06
movq 0x18(%rbx), %rdi
callq 0x3150
movq %r15, %rdi
callq 0x3100
leaq 0x252f(%rip), %rsi      # 0x60c5
movq %rsp, %rdi
callq 0x3270
movq %rax, 0x30(%rbx)
addq $0x3108, %rsp           # imm = 0x3108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x6435(%rip), %rax      # 0x9ff0
movq (%rax), %rcx
leaq 0x241b(%rip), %rdi      # 0x5fe0
pushq $0x3a
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
jmp 0x3ad3
movq 0x6414(%rip), %rax      # 0x9ff0
movq (%rax), %rdi
movq %r14, %rdx
shrq $0x5, %rdx
leaq 0x244e(%rip), %rsi      # 0x603b
xorl %eax, %eax
callq 0x31c0
jmp 0x3ad6
movq 0x63f0(%rip), %rax      # 0x9ff0
movq (%rax), %rcx
leaq 0x2493(%rip), %rdi      # 0x609d
pushq $0x27
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
jmp 0x3c32
movq 0x63d2(%rip), %rax      # 0x9ff0
movq (%rax), %rdi
leaq 0x23f3(%rip), %rsi      # 0x601b
movq %r14, %rdx
xorl %eax, %eax
callq 0x31c0
pushq $0x1
popq %rdi
callq 0x3280