// File: moyix[P]pandalog_taint_parser/label_pcs.cpp
// Function: main
int main(int argc, char **argv) {
    int fd = open(argv[1], O_RDONLY);
    struct stat st;
    stat(argv[1], &st);
    plog = (uint8_t *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    //printf("Mapped at %p\n", plog);
    hdr = (PlHeader *)plog;
    printf("PandaLog v%u with directory at %" PRId64 " chunk size %x\n",
        hdr->version, hdr->dir_pos, hdr->chunk_size);
    dir = (PlDir *)(plog + hdr->dir_pos);
    //printf("Directory entries in pandalog: %u\n", dir->num_entries);
    total_chunks = dir->num_entries;
    chunks = (PlChunk *) malloc(sizeof(PlChunk) * total_chunks);
    //printf("Dumping directory:\n");
    for (int i = 0; i < total_chunks; i++) {
        chunks[i].start = dir->entries[i].start;
        if (i+1 != total_chunks)
            chunks[i].size = dir->entries[i+1].start - chunks[i].start;
        else
            chunks[i].size = hdr->dir_pos - chunks[i].start;
        //printf("  %zu - %zu\n", chunks[i].start, chunks[i].start+chunks[i].size);
    }

    int ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t)*ncpu);
    arg *thread_args = (arg *) malloc(sizeof(arg)*ncpu); 
    for (int i = 0; i < ncpu; i++) {
        thread_args[i].start = (total_chunks / ncpu) * i;
        thread_args[i].size = (i < ncpu - 1) ? 
            (total_chunks / ncpu) : (total_chunks - thread_args[i].start);
        //printf("Creating thread to process Chunks %u - %u\n", thread_args[i].start, thread_args[i].start+thread_args[i].size);
        pthread_create(&threads[i], NULL, process_chunks, &thread_args[i]);
    }
    pthread_t progress_thread;
    pthread_create(&progress_thread, NULL, progress_func, NULL);
    for (int i = 0; i < ncpu; i++) {
        pthread_join(threads[i], NULL);
    }
    pthread_join(progress_thread, NULL);

    printf("Final pass to gather PCs...\n");
    std::map<int,std::set<uint64_t>> label_to_pc;
    for (auto kvp : ptr_to_label) {
        for (auto l : kvp.second) {
            label_to_pc[l].insert(ptr_to_pc[kvp.first].begin(), ptr_to_pc[kvp.first].end());
        }
    }

    FILE *f = fopen("label_pcs.txt", "w");
    for (auto kvp : label_to_pc) {
        fprintf(f, "%d", kvp.first);
        for (auto pc : kvp.second)
            fprintf(f, " %#lx", pc);
        fprintf(f, "\n");
    }
    fclose(f);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
xorl %esi, %esi
movb $0x0, %al
callq 0x6250
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x6310
movq -0x78(%rbp), %rsi
movl -0x14(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x1, %edx
movl $0x2, %ecx
movq %r9, %rdi
callq 0x6650
movq %rax, 0x40539(%rip)     # 0x47650
movq 0x40532(%rip), %rax     # 0x47650
movq %rax, 0x4053b(%rip)     # 0x47660
movq 0x40534(%rip), %rax     # 0x47660
movl (%rax), %esi
movq 0x4052b(%rip), %rax     # 0x47660
movq 0x8(%rax), %rdx
movq 0x40520(%rip), %rax     # 0x47660
movl 0x10(%rax), %ecx
leaq 0x2bfa9(%rip), %rdi     # 0x330f3
movb $0x0, %al
callq 0x6040
movq 0x404f8(%rip), %rax     # 0x47650
movq 0x40501(%rip), %rcx     # 0x47660
addq 0x8(%rcx), %rax
movq %rax, 0x404fe(%rip)     # 0x47668
movq 0x404f7(%rip), %rax     # 0x47668
movl (%rax), %eax
movl %eax, 0x405ab(%rip)     # 0x47724
movslq 0x405a4(%rip), %rdi     # 0x47724
shlq $0x4, %rdi
callq 0x6470
movq %rax, 0x404c8(%rip)     # 0x47658
movl $0x0, -0xac(%rbp)
movl -0xac(%rbp), %eax
cmpl 0x4057e(%rip), %eax     # 0x47724
jge 0x7299
movq 0x404b5(%rip), %rax     # 0x47668
addq $0x4, %rax
movslq -0xac(%rbp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rcx
movq 0x40488(%rip), %rax     # 0x47658
movslq -0xac(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movl -0xac(%rbp), %eax
addl $0x1, %eax
cmpl 0x40534(%rip), %eax     # 0x47724
je 0x7247
movq 0x4046f(%rip), %rax     # 0x47668
addq $0x4, %rax
movl -0xac(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rcx
movq 0x4043d(%rip), %rax     # 0x47658
movslq -0xac(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
subq (%rax), %rcx
movq 0x40425(%rip), %rax     # 0x47658
movslq -0xac(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
jmp 0x7283
movq 0x40412(%rip), %rax     # 0x47660
movq 0x8(%rax), %rcx
movq 0x403ff(%rip), %rax     # 0x47658
movslq -0xac(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
subq (%rax), %rcx
movq 0x403e7(%rip), %rax     # 0x47658
movslq -0xac(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
jmp 0x7285
movl -0xac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
jmp 0x719a
movl $0x54, %edi
callq 0x6200
movl %eax, -0xb0(%rbp)
movslq -0xb0(%rbp), %rdi
shlq $0x3, %rdi
callq 0x6470
movq %rax, -0xb8(%rbp)
movslq -0xb0(%rbp), %rdi
shlq $0x3, %rdi
callq 0x6470
movq %rax, -0xc0(%rbp)
movl $0x0, -0xc4(%rbp)
movl -0xc4(%rbp), %eax
cmpl -0xb0(%rbp), %eax
jge 0x73c5
movl 0x4042b(%rip), %eax     # 0x47724
cltd
idivl -0xb0(%rbp)
movl %eax, %edx
imull -0xc4(%rbp), %edx
movq -0xc0(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl %edx, (%rax,%rcx,8)
movl -0xc4(%rbp), %eax
movl -0xb0(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x7342
movl 0x403f1(%rip), %eax     # 0x47724
cltd
idivl -0xb0(%rbp)
movl %eax, -0x1fc(%rbp)
jmp 0x735f
movl 0x403dc(%rip), %eax     # 0x47724
movq -0xc0(%rbp), %rcx
movslq -0xc4(%rbp), %rdx
subl (%rcx,%rdx,8), %eax
movl %eax, -0x1fc(%rbp)
movl -0x1fc(%rbp), %edx
movq -0xc0(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,8)
movq -0xb8(%rbp), %rdi
movslq -0xc4(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0xc0(%rbp), %rcx
movslq -0xc4(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rcx
xorl %eax, %eax
movl %eax, %esi
leaq -0xa0c(%rip), %rdx      # 0x69a0
callq 0x6660
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x72e1
leaq -0xd0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x437(%rip), %rdx      # 0x6fa0
movq %rcx, %rsi
callq 0x6660
movl $0x0, -0xd4(%rbp)
movl -0xd4(%rbp), %eax
cmpl -0xb0(%rbp), %eax
jge 0x7423
movq -0xb8(%rbp), %rax
movslq -0xd4(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6300
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x73e9
movq -0xd0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6300
leaq 0x2bceb(%rip), %rdi     # 0x33125
movb $0x0, %al
callq 0x6040
leaq -0x108(%rbp), %rdi
callq 0x7ea0
leaq 0x40274(%rip), %rax     # 0x476c8
movq %rax, -0x110(%rbp)
leaq 0x40266(%rip), %rdi     # 0x476c8
callq 0x7ec0
movq %rax, -0x118(%rbp)
leaq 0x40253(%rip), %rdi     # 0x476c8
callq 0x7ef0
movq %rax, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x7f20
testb $0x1, %al
jne 0x749d
jmp 0x7622
leaq -0x118(%rbp), %rdi
callq 0x7f50
movq %rax, %rsi
leaq -0x140(%rbp), %rdi
callq 0x7f70
jmp 0x74ba
leaq -0x140(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rdi
callq 0x7fb0
movq %rax, -0x160(%rbp)
movq -0x158(%rbp), %rdi
callq 0x7fe0
movq %rax, -0x168(%rbp)
leaq -0x160(%rbp), %rdi
leaq -0x168(%rbp), %rsi
callq 0x8010
testb $0x1, %al
jne 0x750e
jmp 0x7605
leaq -0x160(%rbp), %rdi
callq 0x8050
movl (%rax), %eax
movl %eax, -0x16c(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x16c(%rbp), %rsi
callq 0x8070
movq %rax, -0x208(%rbp)
jmp 0x753e
leaq 0x4012b(%rip), %rdi     # 0x47670
leaq -0x140(%rbp), %rsi
callq 0x8190
movq %rax, -0x210(%rbp)
jmp 0x755a
movq -0x210(%rbp), %rdi
callq 0x8270
movq %rax, -0x178(%rbp)
leaq 0x400fc(%rip), %rdi     # 0x47670
leaq -0x140(%rbp), %rsi
callq 0x8190
movq %rax, -0x218(%rbp)
jmp 0x7589
movq -0x218(%rbp), %rdi
callq 0x82a0
movq -0x208(%rbp), %rdi
movq %rax, -0x180(%rbp)
movq -0x178(%rbp), %rsi
movq -0x180(%rbp), %rdx
callq 0x8150
jmp 0x75b8
jmp 0x75ba
leaq -0x160(%rbp), %rdi
callq 0x82d0
jmp 0x74f2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x148(%rbp)
movl %eax, -0x14c(%rbp)
jmp 0x77c4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x148(%rbp)
movl %eax, -0x14c(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x82f0
jmp 0x77c4
leaq -0x140(%rbp), %rdi
callq 0x82f0
leaq -0x118(%rbp), %rdi
callq 0x8310
jmp 0x7481
leaq 0x2bb19(%rip), %rdi     # 0x33142
leaq 0x2bb20(%rip), %rsi     # 0x33150
callq 0x6400
movq %rax, -0x220(%rbp)
jmp 0x763e
movq -0x220(%rbp), %rax
movq %rax, -0x188(%rbp)
leaq -0x108(%rbp), %rax
movq %rax, -0x190(%rbp)
movq -0x190(%rbp), %rdi
callq 0x8340
movq %rax, -0x198(%rbp)
movq -0x190(%rbp), %rdi
callq 0x8370
movq %rax, -0x1a0(%rbp)
leaq -0x198(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x83a0
testb $0x1, %al
jne 0x769c
jmp 0x7797
leaq -0x198(%rbp), %rdi
callq 0x83d0
movq %rax, %rsi
leaq -0x1d8(%rbp), %rdi
callq 0x83f0
jmp 0x76b9
movq -0x188(%rbp), %rdi
movl -0x1d8(%rbp), %edx
leaq 0x2ba85(%rip), %rsi     # 0x33152
movb $0x0, %al
callq 0x64e0
leaq -0x1d8(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x1e0(%rbp)
movq -0x1e0(%rbp), %rdi
callq 0x8270
movq %rax, -0x1e8(%rbp)
movq -0x1e0(%rbp), %rdi
callq 0x82a0
movq %rax, -0x1f0(%rbp)
leaq -0x1e8(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x8430
testb $0x1, %al
jne 0x7725
jmp 0x7765
leaq -0x1e8(%rbp), %rdi
callq 0x8460
movq (%rax), %rax
movq %rax, -0x1f8(%rbp)
movq -0x188(%rbp), %rdi
movq -0x1f8(%rbp), %rdx
leaq 0x2ba05(%rip), %rsi     # 0x33155
movb $0x0, %al
callq 0x64e0
leaq -0x1e8(%rbp), %rdi
callq 0x8480
jmp 0x770c
movq -0x188(%rbp), %rdi
leaq 0x2b9cd(%rip), %rsi     # 0x33140
movb $0x0, %al
callq 0x64e0
leaq -0x1d8(%rbp), %rdi
callq 0x84b0
leaq -0x198(%rbp), %rdi
callq 0x84d0
jmp 0x7680
movq -0x188(%rbp), %rdi
callq 0x6360
jmp 0x77a5
movl $0x0, -0x4(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x8500
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
leaq -0x108(%rbp), %rdi
callq 0x8500
movq -0x148(%rbp), %rdi
callq 0x6630
nopl (%rax)