// File: /workspace/github_c_makefile_star2_O2/melynx[P]peekaboo/libpeekaboo/libpeekaboo.c
// Function: load_trace
void load_trace(char *dir_path, peekaboo_trace_t *trace_ptr)
{
	char path[MAX_PATH];

	// Load metadata first
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "metafile");
	trace_ptr->metafile = fopen(path, "rb");
	if (trace_ptr->metafile == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load %s\n", path);

	// Creates the internal data-structure to store the
	// meta-information about the loaded trace
	trace_ptr->internal = malloc(sizeof(peekaboo_internal_t));
	memset(trace_ptr->internal, 0, sizeof(peekaboo_internal_t));

	// Setup the information
	metadata_hdr_t meta;
	size_t fread_bytes = fread(&meta, sizeof(metadata_hdr_t), 1, trace_ptr->metafile);
	trace_ptr->internal->arch = meta.arch;
	trace_ptr->internal->version = meta.version;
	fprintf(stderr, "Trace's libpeekaboo version: %d\n", meta.version);
	fclose(trace_ptr->metafile);

	if (trace_ptr->internal->version >= 4)
	{
		// New trace format that can customize which registers to store
		if (trace_ptr->internal->arch == ARCH_AMD64)
		{
			trace_ptr->internal->storage_options.amd64.has_simd = meta.storage_options.amd64.has_simd;
			trace_ptr->internal->storage_options.amd64.has_fxsave = meta.storage_options.amd64.has_fxsave;
			fprintf(stderr, "Stored register: GPRs ");
			if (trace_ptr->internal->storage_options.amd64.has_simd) fprintf(stderr, "SIMD ");
			if (trace_ptr->internal->storage_options.amd64.has_fxsave) fprintf(stderr, "FXSAVE ");
			fprintf(stderr, "\n");
		}
	}
	else
	{
		// Trace version lower than 003, stores everything
		trace_ptr->internal->storage_options.amd64.has_simd = 1;
		trace_ptr->internal->storage_options.amd64.has_fxsave = 1;
	}

	switch (meta.arch)
	{
		case ARCH_AMD64:
			trace_ptr->internal->ptr_size = 8;
			trace_ptr->internal->regfile_size = sizeof(regfile_amd64_t);
			break;
		case ARCH_AARCH64:
			trace_ptr->internal->ptr_size = 8;
			trace_ptr->internal->regfile_size = sizeof(regfile_aarch64_t);
			break;
		case ARCH_X86:
			trace_ptr->internal->ptr_size = 4;
			trace_ptr->internal->regfile_size = sizeof(regfile_x86_t);
			break;
		default:
			trace_ptr->internal->ptr_size = 0;
			trace_ptr->internal->regfile_size = 0;
			break;
	}

	// Load bytes_map based on the version
	if (meta.version > 1)
		snprintf(path, MAX_PATH, "%s/../%s", dir_path, "insn.bytemap");
	else
		// Legacy trace format in Verion 1 which does not have separate folders for different threads.
		snprintf(path, MAX_PATH, "%s/%s", dir_path, "insn.bytemap");
	trace_ptr->bytes_map = fopen(path, "rb");
	if (trace_ptr->bytes_map == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load bytes_map\n");

	// Load insn.trace, regfile, memfile, memrefs.
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "insn.trace");
	trace_ptr->insn_trace = fopen(path, "rb");
	if (trace_ptr->insn_trace == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load %s\n", path);
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "regfile");
	trace_ptr->regfile = fopen(path, "rb");
	if (trace_ptr->regfile == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load %s\n", path);
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "memfile");
	trace_ptr->memfile = fopen(path, "rb");
	if (trace_ptr->memfile == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load %s\n", path);
	snprintf(path, MAX_PATH, "%s/%s", dir_path, "memrefs");
	trace_ptr->memrefs = fopen(path, "rb");
	if (trace_ptr->memrefs == NULL) PEEKABOO_DIE("libpeekaboo: Unable to load %s\n", path);

	// Init for internal structure
	size_t trace_size = 0;
	size_t ptr_size = trace_ptr->internal->ptr_size;
	fseek(trace_ptr->insn_trace, 0, SEEK_END);
	trace_size = ftell(trace_ptr->insn_trace);
	rewind(trace_ptr->insn_trace);
	trace_ptr->internal->num_insns = trace_size/ptr_size;

	// loads the rawbytes map for the trace
	load_bytes_map(trace_ptr);

	// load memrefs_offsets. Create if not exist 
	load_memrefs_offsets(dir_path, trace_ptr);

	// All good. Ready to go~!
	return ;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x2372(%rip), %r15      # 0x5fca
leaq 0x22de(%rip), %r8       # 0x5f3d
leaq 0x10(%rsp), %r12
movl $0x100, %esi            # imm = 0x100
movq %r12, %rdi
movq %r15, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x2445(%rip), %rsi      # 0x60c5
movq %r12, %rdi
callq 0x3270
movq %rax, 0x28(%rbx)
testq %rax, %rax
je 0x3f98
movq %rax, %r12
pushq $0x1
popq %r13
pushq $0x68
popq %rsi
movq %r13, %rdi
callq 0x31b0
movq %rax, 0x38(%rbx)
movq %rsp, %rbp
pushq $0x10
popq %rsi
movq %rbp, %rdi
movq %r13, %rdx
movq %r12, %rcx
callq 0x30e0
movl (%rbp), %r12d
movq 0x38(%rbx), %rax
movl %r12d, (%rax)
movl 0x4(%rbp), %ebp
movl %ebp, 0x58(%rax)
movq 0x6319(%rip), %r13      # 0x9ff0
movq (%r13), %rdi
leaq 0x2406(%rip), %rsi      # 0x60e8
movl %ebp, %edx
xorl %eax, %eax
callq 0x31c0
movq 0x28(%rbx), %rdi
callq 0x3100
movq 0x38(%rbx), %rax
cmpl $0x4, 0x58(%rax)
jb 0x3d51
cmpl $0x3, (%rax)
jne 0x3d5e
movl 0x8(%rsp), %ecx
movl %ecx, 0x60(%rax)
movl 0xc(%rsp), %eax
movq 0x38(%rbx), %rcx
movl %eax, 0x64(%rcx)
movq (%r13), %rcx
leaq 0x23e9(%rip), %rdi      # 0x6109
pushq $0x16
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
movq 0x38(%rbx), %rax
cmpl $0x0, 0x60(%rax)
jne 0x3f5e
cmpl $0x0, 0x64(%rax)
jne 0x3f7d
movq (%r13), %rsi
pushq $0xa
popq %rdi
callq 0x31a0
jmp 0x3d5e
pushq $0x1
popq %rcx
movl %ecx, 0x60(%rax)
movq 0x38(%rbx), %rax
movl %ecx, 0x64(%rax)
movq 0x38(%rbx), %rax
cmpl $0x1, %r12d
je 0x3d98
cmpl $0x2, %r12d
je 0x3d86
cmpl $0x3, %r12d
jne 0x3daa
movq $0x8, 0x8(%rax)
movq $0x490, 0x10(%rax)      # imm = 0x490
jmp 0x3db4
movq $0x4, 0x8(%rax)
movq $0x20, 0x10(%rax)
jmp 0x3db4
movq $0x8, 0x8(%rax)
movq $0x318, 0x10(%rax)      # imm = 0x318
jmp 0x3db4
addq $0x8, %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
cmpl $0x2, %ebp
leaq 0x2370(%rip), %rax      # 0x612e
cmovaeq %rax, %r15
leaq 0x236e(%rip), %r8       # 0x6137
leaq 0x10(%rsp), %r12
movl $0x100, %esi            # imm = 0x100
movq %r12, %rdi
movq %r15, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x22db(%rip), %rsi      # 0x60c5
movq %r12, %rdi
callq 0x3270
movq %rax, 0x8(%rbx)
testq %rax, %rax
je 0x3fc3
leaq 0x21c4(%rip), %rdx      # 0x5fca
leaq 0x210d(%rip), %r8       # 0x5f1a
leaq 0x10(%rsp), %r15
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x229a(%rip), %rsi      # 0x60c5
movq %r15, %rdi
callq 0x3270
movq %rax, (%rbx)
testq %rax, %rax
je 0x3fbd
leaq 0x2184(%rip), %rdx      # 0x5fca
leaq 0x20d8(%rip), %r8       # 0x5f25
leaq 0x10(%rsp), %r15
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x225a(%rip), %rsi      # 0x60c5
movq %r15, %rdi
callq 0x3270
movq %rax, 0x10(%rbx)
testq %rax, %rax
je 0x3fbd
leaq 0x2143(%rip), %rdx      # 0x5fca
leaq 0x209f(%rip), %r8       # 0x5f2d
leaq 0x10(%rsp), %r15
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x2219(%rip), %rsi      # 0x60c5
movq %r15, %rdi
callq 0x3270
movq %rax, 0x20(%rbx)
testq %rax, %rax
je 0x3fbd
leaq 0x2102(%rip), %rdx      # 0x5fca
leaq 0x2066(%rip), %r8       # 0x5f35
leaq 0x10(%rsp), %r15
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x3160
leaq 0x21d8(%rip), %rsi      # 0x60c5
movq %r15, %rdi
callq 0x3270
movq %rax, 0x18(%rbx)
testq %rax, %rax
je 0x3fbd
movq (%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %r12
pushq $0x2
popq %rdx
xorl %esi, %esi
callq 0x3240
movq (%rbx), %rdi
callq 0x31d0
movq %rax, %r15
movq (%rbx), %rdi
callq 0x3150
movq %r15, %rax
xorl %edx, %edx
divq %r12
movq 0x38(%rbx), %rcx
movq %rax, 0x28(%rcx)
movq %rbx, %rdi
callq 0x3260
movq %r14, %rdi
movq %rbx, %rsi
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x31e0
movq (%r13), %rcx
leaq 0x21b7(%rip), %rdi      # 0x6120
pushq $0x5
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
movq 0x38(%rbx), %rax
jmp 0x3d39
movq (%r13), %rcx
leaq 0x219e(%rip), %rdi      # 0x6126
pushq $0x7
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
jmp 0x3d43
movq 0x6051(%rip), %rax      # 0x9ff0
movq (%rax), %rdi
leaq 0x211f(%rip), %rsi      # 0x60c8
leaq 0x10(%rsp), %rdx
xorl %eax, %eax
callq 0x31c0
pushq $0x1
popq %rdi
callq 0x3280
movq (%r13), %rdi
jmp 0x3fa2
movq (%r13), %rcx
leaq 0x2176(%rip), %rdi      # 0x6144
pushq $0x26
popq %rsi
pushq $0x1
popq %rdx
callq 0x3290
jmp 0x3fb5