// File: coduin[P]epiphany-bin-info/epiphany-bin-info.cpp
// Function: parseSymbolTable(Elf32_Sym*, unsigned long, char const*, unsigned long)
void parseSymbolTable(Elf32_Sym* symbol, size_t count, const char* symstr,
                      size_t symstrsize) {
    Symbol sym;
    for (size_t i = 0; i < count; i++) {
        sym.index = i;
        sym.value = symbol[i].st_value;
        sym.size = symbol[i].st_size;
        sym.type = ELF32_ST_TYPE(symbol[i].st_info);
        sym.bind = ELF32_ST_BIND(symbol[i].st_info);
        sym.section = symbol[i].st_shndx;
        if (symbol[i].st_name < symstrsize)
            sym.name = ((char*)(&symstr[symbol[i].st_name]));
        else
            sym.name.clear();

        if (demangleNames)
            sym.name = demangle(sym.name);

        symbols.push_back(sym);
    }
    sort(symbols.begin(), symbols.end());

    if (showSymbols) {
        cout << "\nSymbol table contains " << count << " symbols." << endl;
        cout << "Showing only global symbols. Highlighting symbol sizes larger "
                "than 128 Bytes (local) or 1024 Bytes (external)."
             << endl;
        cout << "VALUE        SIZE TYPE    SEC NAME\n";
        for (size_t i = 0; i < symbols.size(); i++) {
            Symbol& sym = symbols[i];
            bool is_large = false;
            if (isExtmem(sym.value)) {
                is_large = sym.size > 1024;
            } else {
                is_large = sym.size > 128;
            }
            if (sym.bind == STB_GLOBAL) {
                cout << addr(sym.value);

                if (is_large)
                    outputSetPurple();
                cout << ' ' << dec << setfill(' ') << setw(6) << sym.size;
                outputReset();

                switch (sym.type) {
                case STT_NOTYPE:
                    cout << " NOTYPE ";
                    break;
                case STT_OBJECT:
                    cout << " OBJECT ";
                    break;
                case STT_FUNC:
                    cout << " FUNC   ";
                    break;
                case STT_SECTION:
                    cout << " SECTION";
                    break;
                case STT_FILE:
                    cout << " FILE   ";
                    break;
                default:
                    cout << " Unknown";
                    break;
                }

                switch (sym.section) {
                case SHN_ABS:
                    cout << " ABS";
                    break;
                case SHN_COMMON:
                    cout << " COM";
                    break;
                case SHN_UNDEF:
                    cout << " UND";
                    break;
                default:
                    cout << dec << setw(4) << setfill(' ') << sym.section;
                    break;
                }

                cout << ' ' << sym.name;
                cout << endl;
            }
        }
        cout << dec;
    }
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x160(%rsp)
movq %rsi, 0x158(%rsp)
movq %rdx, 0x150(%rsp)
movq %rcx, 0x148(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x47f0
movq $0x0, 0x108(%rsp)
movq 0x108(%rsp), %rax
cmpq 0x158(%rsp), %rax
jae 0x322a
movq 0x108(%rsp), %rax
movl %eax, 0x110(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movl %eax, 0x114(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, 0x118(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movzbl 0xc(%rax), %eax
andl $0xf, %eax
movl %eax, 0x11c(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movzbl 0xc(%rax), %eax
sarl $0x4, %eax
movl %eax, 0x120(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movzwl 0xe(%rax), %eax
movl %eax, 0x124(%rsp)
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
cmpq 0x148(%rsp), %rax
jae 0x31a2
movq 0x150(%rsp), %rsi
movq 0x160(%rsp), %rax
movq 0x108(%rsp), %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %eax
addq %rax, %rsi
leaq 0x128(%rsp), %rdi
callq 0x2300
jmp 0x3187
jmp 0x31b3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x100(%rsp)
movl %eax, 0xfc(%rsp)
jmp 0x3772
leaq 0x110(%rsp), %rdi
addq $0x18, %rdi
callq 0x22d0
testb $0x1, 0x804e(%rip)      # 0xb208
je 0x31f9
leaq 0x128(%rsp), %rsi
leaq 0xd8(%rsp), %rdi
callq 0x2770
jmp 0x31d3
leaq 0x110(%rsp), %rdi
addq $0x18, %rdi
leaq 0xd8(%rsp), %rsi
callq 0x2290
leaq 0xd8(%rsp), %rdi
callq 0x2140
leaq 0x8028(%rip), %rdi      # 0xb228
leaq 0x110(%rsp), %rsi
callq 0x4810
jmp 0x320f
jmp 0x3211
movq 0x108(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x108(%rsp)
jmp 0x3060
leaq 0x7ff7(%rip), %rdi      # 0xb228
movq %rdi, 0x98(%rsp)
callq 0x48c0
movq 0x98(%rsp), %rdi
movq %rax, 0xd0(%rsp)
callq 0x48f0
movq %rax, 0xc8(%rsp)
movq 0xd0(%rsp), %rdi
movq 0xc8(%rsp), %rsi
callq 0x4880
jmp 0x3272
testb $0x1, 0x7fab(%rip)      # 0xb224
je 0x375d
movq 0x7d4a(%rip), %rdi      # 0xafd0
leaq 0x4e92(%rip), %rsi      # 0x811f
callq 0x21d0
movq %rax, 0x90(%rsp)
jmp 0x329c
movq 0x90(%rsp), %rdi
movq 0x158(%rsp), %rsi
callq 0x2070
movq %rax, 0x88(%rsp)
jmp 0x32bb
movq 0x88(%rsp), %rdi
leaq 0x4e6d(%rip), %rsi      # 0x8137
callq 0x21d0
movq %rax, 0x80(%rsp)
jmp 0x32d9
movq 0x80(%rsp), %rdi
movq 0x7cd8(%rip), %rsi      # 0xafc0
callq 0x2200
jmp 0x32ef
movq 0x7cda(%rip), %rdi      # 0xafd0
leaq 0x4e44(%rip), %rsi      # 0x8141
callq 0x21d0
movq %rax, 0x78(%rsp)
jmp 0x3309
movq 0x78(%rsp), %rdi
movq 0x7cab(%rip), %rsi      # 0xafc0
callq 0x2200
jmp 0x331c
movq 0x7cad(%rip), %rdi      # 0xafd0
leaq 0x4e86(%rip), %rsi      # 0x81b0
callq 0x21d0
jmp 0x3331
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, 0x70(%rsp)
leaq 0x7ed7(%rip), %rdi      # 0xb228
callq 0x4920
movq %rax, %rcx
movq 0x70(%rsp), %rax
cmpq %rcx, %rax
jae 0x3746
movq 0xc0(%rsp), %rsi
leaq 0x7eb2(%rip), %rdi      # 0xb228
callq 0x4940
movq %rax, 0xb8(%rsp)
movb $0x0, 0xb7(%rsp)
movq 0xb8(%rsp), %rax
movl 0x4(%rax), %edi
callq 0x2560
testb $0x1, %al
jne 0x33a1
jmp 0x33be
movq 0xb8(%rsp), %rax
cmpl $0x400, 0x8(%rax)       # imm = 0x400
setg %al
andb $0x1, %al
movb %al, 0xb7(%rsp)
jmp 0x33d9
movq 0xb8(%rsp), %rax
cmpl $0x80, 0x8(%rax)
setg %al
andb $0x1, %al
movb %al, 0xb7(%rsp)
movq 0xb8(%rsp), %rax
cmpl $0x1, 0x10(%rax)
jne 0x372b
movq 0xb8(%rsp), %rax
movl 0x4(%rax), %esi
leaq 0xb0(%rsp), %rdi
callq 0x4750
jmp 0x3405
movq 0x7bc4(%rip), %rdi      # 0xafd0
leaq 0xb0(%rsp), %rsi
callq 0x2680
jmp 0x341b
leaq 0xb0(%rsp), %rdi
callq 0x4770
testb $0x1, 0xb7(%rsp)
je 0x3461
callq 0x25a0
jmp 0x3439
jmp 0x3461
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x100(%rsp)
movl %eax, 0xfc(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x4770
jmp 0x3772
movq 0x7b68(%rip), %rdi      # 0xafd0
movl $0x20, %esi
callq 0x2270
movq %rax, 0x68(%rsp)
jmp 0x3479
movq 0x68(%rsp), %rdi
leaq 0x127b(%rip), %rsi      # 0x4700
callq 0x20b0
movq %rax, 0x60(%rsp)
jmp 0x3491
movl $0x20, %edi
callq 0x46a0
movb %al, 0x5f(%rsp)
jmp 0x34a1
movq 0x60(%rsp), %rdi
movb 0x5f(%rsp), %al
movb %al, 0xaf(%rsp)
movzbl 0xaf(%rsp), %esi
callq 0x2340
movq %rax, 0x50(%rsp)
jmp 0x34c5
movl $0x6, %edi
callq 0x46e0
movl %eax, 0x4c(%rsp)
jmp 0x34d5
movq 0x50(%rsp), %rdi
movl 0x4c(%rsp), %eax
movl %eax, 0xa8(%rsp)
movl 0xa8(%rsp), %esi
callq 0x2260
movq %rax, 0x40(%rsp)
jmp 0x34f8
movq 0x40(%rsp), %rdi
movq 0xb8(%rsp), %rax
movl 0x8(%rax), %esi
callq 0x2370
jmp 0x350f
callq 0x25c0
jmp 0x3516
movq 0xb8(%rsp), %rax
movl 0xc(%rax), %eax
movq %rax, 0x38(%rsp)
subq $0x4, %rax
ja 0x35b8
movq 0x38(%rsp), %rax
leaq 0x4ac8(%rip), %rcx      # 0x8004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x7a84(%rip), %rdi      # 0xafd0
leaq 0x4c81(%rip), %rsi      # 0x81d4
callq 0x21d0
jmp 0x355a
jmp 0x35cf
movq 0x7a6d(%rip), %rdi      # 0xafd0
leaq 0x4c73(%rip), %rsi      # 0x81dd
callq 0x21d0
jmp 0x3571
jmp 0x35cf
movq 0x7a56(%rip), %rdi      # 0xafd0
leaq 0x4c65(%rip), %rsi      # 0x81e6
callq 0x21d0
jmp 0x3588
jmp 0x35cf
movq 0x7a3f(%rip), %rdi      # 0xafd0
leaq 0x4c57(%rip), %rsi      # 0x81ef
callq 0x21d0
jmp 0x359f
jmp 0x35cf
movq 0x7a28(%rip), %rdi      # 0xafd0
leaq 0x4c49(%rip), %rsi      # 0x81f8
callq 0x21d0
jmp 0x35b6
jmp 0x35cf
movq 0x7a11(%rip), %rdi      # 0xafd0
leaq 0x4c3b(%rip), %rsi      # 0x8201
callq 0x21d0
jmp 0x35cd
jmp 0x35cf
movq 0xb8(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, 0x34(%rsp)
testl %eax, %eax
je 0x3632
jmp 0x35e4
movl 0x34(%rsp), %eax
subl $0xfff1, %eax           # imm = 0xFFF1
je 0x35fe
jmp 0x35f1
movl 0x34(%rsp), %eax
subl $0xfff2, %eax           # imm = 0xFFF2
je 0x3618
jmp 0x364c
movq 0x79cb(%rip), %rdi      # 0xafd0
leaq 0x4bfe(%rip), %rsi      # 0x820a
callq 0x21d0
jmp 0x3613
jmp 0x36e6
movq 0x79b1(%rip), %rdi      # 0xafd0
leaq 0x4be9(%rip), %rsi      # 0x820f
callq 0x21d0
jmp 0x362d
jmp 0x36e6
movq 0x7997(%rip), %rdi      # 0xafd0
leaq 0x4bd4(%rip), %rsi      # 0x8214
callq 0x21d0
jmp 0x3647
jmp 0x36e6
movq 0x797d(%rip), %rdi      # 0xafd0
leaq 0x10a6(%rip), %rsi      # 0x4700
callq 0x20b0
movq %rax, 0x28(%rsp)
jmp 0x3666
movl $0x4, %edi
callq 0x46e0
movl %eax, 0x24(%rsp)
jmp 0x3676
movq 0x28(%rsp), %rdi
movl 0x24(%rsp), %eax
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %esi
callq 0x2260
movq %rax, 0x18(%rsp)
jmp 0x3699
movl $0x20, %edi
callq 0x46a0
movb %al, 0x17(%rsp)
jmp 0x36a9
movq 0x18(%rsp), %rdi
movb 0x17(%rsp), %al
movb %al, 0xa3(%rsp)
movzbl 0xa3(%rsp), %esi
callq 0x2340
movq %rax, 0x8(%rsp)
jmp 0x36cd
movq 0x8(%rsp), %rdi
movq 0xb8(%rsp), %rax
movl 0x14(%rax), %esi
callq 0x2370
jmp 0x36e4
jmp 0x36e6
movq 0x78e3(%rip), %rdi      # 0xafd0
movl $0x20, %esi
callq 0x2270
movq %rax, (%rsp)
jmp 0x36fd
movq (%rsp), %rdi
movq 0xb8(%rsp), %rsi
addq $0x18, %rsi
callq 0x21c0
jmp 0x3714
movq 0x78b5(%rip), %rdi      # 0xafd0
movq 0x789e(%rip), %rsi      # 0xafc0
callq 0x2200
jmp 0x3729
jmp 0x372b
jmp 0x372d
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x333d
movq 0x7883(%rip), %rdi      # 0xafd0
leaq 0xfac(%rip), %rsi       # 0x4700
callq 0x20b0
jmp 0x375b
jmp 0x375d
leaq 0x110(%rsp), %rdi
callq 0x4960
addq $0x168, %rsp            # imm = 0x168
retq
leaq 0x110(%rsp), %rdi
callq 0x4960
movq 0x100(%rsp), %rdi
callq 0x23a0
nopl (%rax)