NAME=x86_32
FILE=bins/elf/crackme0x05
EXPECT=<<EOF
x86:LE:32:default:gcc

uint main(int argc,char **argv,char **envp)

{
    int32_t var_78h;
    
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    sym.imp.scanf(0x80486b2,&var_78h);
    sym.check(&var_78h);
    return 0;
}

EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN

NAME=x86_32
FILE=bins/elf/crackme0x05
EXPECT=<<EOF
                                                |
    0x08048540 push ebp                         |uint main(int argc,char **argv,char **envp)
                                                |
                                                |{
                                                |    int32_t var_78h;
                                                |    
    0x08048566 call sym.imp.printf              |    sym.imp.printf("IOLI Crackme Level 0x05\n");
    0x08048572 call sym.imp.printf              |    sym.imp.printf("Password: ");
    0x08048585 call sym.imp.scanf               |    sym.imp.scanf(0x80486b2,&var_78h);
    0x08048590 call sym.check                   |    sym.check(&var_78h);
    0x0804859b ret                              |    return 0;
                                                |}
                                                |
x86
x86:LE:32:default:gcc

uint main(int argc,char **argv,char **envp)

{
    int32_t var_78h;
    
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    sym.imp.scanf(0x80486b2,&var_78h);
    sym.check(&var_78h);
    return 0;
}

EOF
CMDS=<<EOF
s main
af
pdga
e asm.arch
pdgss
pdg
EOF
RUN

NAME=x86_64
FILE=bins/elf/hello_world
EXPECT=<<EOF
x86:LE:64:default:gcc

void main(int argc,char **argv,char **envp)

{
    int iVar1;
    int iVar2;
    char *dest;
    int32_t var_20h;
    int32_t var_1ch;
    int64_t var_18h;
    int64_t var_10h;
    int64_t var_8h;
    
    iVar1 = sym.imp.strlen("Hello");
    iVar2 = sym.imp.strlen(" r2-folks");
    dest = sym.imp.malloc(iVar2 + iVar1 + 1);
    if (dest != NULL) {
        sym.imp.strcpy(dest,"Hello");
        sym.imp.strcat(dest," r2-folks");
        sym.imp.puts(dest);
        sym.imp.free(dest);
    }
    return;
}

EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN

NAME=x86_16
FILE=bins/mz/unzip.exe
EXPECT=<<EOF
x86:LE:16:Real Mode:

//WARNING: Variable defined which should be unmapped: var_8h
//WARNING: Variable defined which should be unmapped: var_4h

uint fcn.00001c98(ushort noname_0,ushort noname_1,int16_t arg_ah,int16_t noname_3,int16_t arg_eh)

{
    int16_t *piVar1;
    ushort unaff_CS;
    ushort unaff_DS;
    uint uVar2;
    int16_t in_stack_0000000c;
    int16_t var_8h;
    int16_t var_6h;
    int16_t var_4h;
    int8_t var_2h;
    char cStack_4;
    
    var_6h = 0x13da;
    do {
        func_0x0000ec24(unaff_CS,var_6h,unaff_DS,0x401e);
        func_0x0000ec24(0xdee,noname_1,arg_ah,0x401e);
        func_0x0000e59a(0xdee,0x401e);
        _var_2h = 0;
        do {
            cStack_4 = func_0x0000eb82(0xdee);
            if (cStack_4 == '\r') {
                cStack_4 = '\n';
            }
            if (_var_2h < in_stack_0000000c) {
                *(noname_3 + _var_2h) = cStack_4;
                _var_2h = _var_2h + 1;
            }
        } while (cStack_4 != '\n');
        piVar1 = 0x4022;
        *piVar1 = *piVar1 + -1;
        if (*piVar1 < 0) {
            func_0x0000e4ae(0xdee,10,0x401e);
        }
        else {
            **0x401e = 10;
            *0x401e = *0x401e + 1;
        }
        unaff_CS = 0xdee;
        func_0x0000e59a(0xdee,0x401e);
        var_6h = 0x13db;
    } while (*(noname_3 + _var_2h + -1) != '\n');
    *(noname_3 + _var_2h + -1) = 0;
    return uVar2;
}

EOF
CMDS=<<EOF
pdgss
s 0x1c98
af
pdg
EOF
RUN

NAME=x86_64
FILE=bins/elf/hello_world
EXPECT=<<EOF
x86:LE:64:default:gcc

void main(int argc,char **argv,char **envp)

{
    int iVar1;
    int iVar2;
    char *dest;
    int32_t var_20h;
    int32_t var_1ch;
    int64_t var_18h;
    int64_t var_10h;
    int64_t var_8h;
    
    iVar1 = sym.imp.strlen("Hello");
    iVar2 = sym.imp.strlen(" r2-folks");
    dest = sym.imp.malloc(iVar2 + iVar1 + 1);
    if (dest != NULL) {
        sym.imp.strcpy(dest,"Hello");
        sym.imp.strcat(dest," r2-folks");
        sym.imp.puts(dest);
        sym.imp.free(dest);
    }
    return;
}

EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN


NAME=6502
FILE=bins/prg/t01.prg
ARGS=-F prg
EXPECT=<<EOF
6502:LE:16:default:

void fcn.0000080e(void)

{
    uchar uVar1;
    uint8_t uVar2;
    
    uVar2 = 0xff;
    do {
        *(uVar2 + 0x3ff) = 0x41;
        uVar1 = *0x824;
        uVar2 = uVar2 - 1;
    } while (uVar2 != 0);
    uVar2 = 0xff;
    do {
        *(uVar2 + 0xd7ff) = uVar1;
        uVar2 = uVar2 - 1;
    } while (uVar2 != 0);
    return;
}

EOF
CMDS=<<EOF
pdgss
s 0x080e
af
pdg
EOF
RUN


NAME=macos args
FILE=bins/mach0/arg
EXPECT=<<EOF

void main(int argc,char **argv,char **envp)

{
    int32_t var_4h;
    
    sym._call("hello",0x100000faa);
    return;
}

EOF
CMDS=<<EOF
aaa
s main
pdg
EOF
RUN

NAME=Nodup function on container query
FILE=bins/hello-arm
EXPECT=<<EOF

//WARNING: Control flow encountered bad instruction data

void entry0(void)

{
    //[11] -r-x section size 200 named .text
    rsym.__libc_init();
    //WARNING: Bad instruction - Truncating control flow here
    halt_baddata();
}

EOF
CMDS=<<EOF
s entry0
af
pdg
EOF
RUN

# needs the anal.gp auto-seeding added to radare2 after the 6.1.8 release
NAME=mips gp-relative import argument resolves under pdg
BROKEN=1
FILE=bins/elf/boa-mips-mini
CMDS=<<EOF
0x00400500;af;pdg~sym.imp.umask,sym.imp.time
EOF
EXPECT=<<EOF
    sym.imp.umask(0x3f);
    sym.imp.time(_reloc.current_time);
EOF
RUN

NAME=mips t9 seed removes phantom gp args under pdg
FILE=bins/elf/boa-mips-mini
CMDS=<<EOF
0x00400580;af;pdg
EOF
EXPECT=<<EOF

uint32_t sym.isFileExist(uint param_1)

{
    uint32_t uVar1;
    uchar auStack_a0 [152];
    
    uVar1 = sym.imp.stat(param_1,auStack_a0);
    return ~uVar1 >> 0x1f;
}

EOF
RUN

NAME=ppc64 et_rel reloc call target resolves to named function under pdg
FILE=bins/elf/ppc64v1-crc32_generic.ko
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF
aa
pdg @ sym..crc32_init
EOF
EXPECT=<<EOF

ulong sym..crc32_init(int64_t arg1)

{
    reloc.._mcount();
    *(arg1 + 8) = *(*arg1 + 0x20);
    return 0;
}

EOF
RUN

NAME=ppc64 sign-prefixed register arg keeps its 64-bit width under pdg
FILE=bins/elf/ppc64v1-crc32_generic.ko
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF
aa
afvt arg1 signed int64_t @ sym..crc32_init
pdg @ sym..crc32_init
EOF
EXPECT=<<EOF

ulong sym..crc32_init(int64_t arg1)

{
    reloc.._mcount();
    *(arg1 + 8) = *(*arg1 + 0x20);
    return 0;
}

EOF
RUN

NAME=ppc64 big-endian narrow register arg maps to low-order bytes under pdg
FILE=bins/elf/ppc64v1-crc32_generic.ko
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF
aa
afvt arg3 int @ sym..crc32_setkey
pdg @ sym..crc32_setkey~arg3
EOF
EXPECT=<<EOF
int64_t sym..crc32_setkey(int64_t arg1,int64_t arg2,int arg3)
    if (arg3 == 4) {
EOF
RUN

NAME=ppc32 small-data r2 seed resolves sdata globals under pdg
FILE=bins/elf/ppc32-sda
ARGS=-e anal.gp=0x1000801c
CMDS=<<EOF
s sym.get_sda
af
pdg
EOF
EXPECT=<<EOF

int sym.get_sda(void)

{
    return _loc.gv1 + _loc.gv2;
}

EOF
RUN

NAME=ppc32 small-data loads stay unresolved without r2 seed
FILE=bins/elf/ppc32-sda
ARGS=-e anal.gp=0
CMDS=<<EOF
s sym.get_sda
af
pdg
EOF
EXPECT=<<EOF

int sym.get_sda(void)

{
    int unaff_r2;
    
    return *(unaff_r2 + -0x8000) + *(unaff_r2 + -0x7ffc);
}

EOF
RUN

NAME=ppc32 e500mc sleigh auto-selected from apuinfo cpu
FILE=bins/elf/ppc32-e500mc-isel
CMDS=<<EOF
pdgss
EOF
EXPECT=<<EOF
PowerPC:BE:32:e500mc:default
EOF
RUN

NAME=ppc64 isel selects 64-bit-address A2ALT sleigh variant
FILE=bins/elf/ppc64-isel
CMDS=<<EOF
pdgss
EOF
EXPECT=<<EOF
PowerPC:BE:64:A2ALT:default
EOF
RUN

NAME=ppc64 isel decompiles as conditional select under A2ALT
FILE=bins/elf/ppc64-isel
CMDS=<<EOF
aa
s 0x10000000
af
pdg
EOF
EXPECT=<<EOF

ulong fcn.10000000(ulong param_1,ulong param_2)

{
    uint8_t in_cr0;
    
    //[01] -r-x section size 16 named .text
    if (in_cr0 >> 3 & 1) {
        param_1 = param_2;
    }
    return param_1;
}

EOF
RUN

NAME=stop at noreturn call before data
FILE=bins/elf/arm-stackchk
CMDS=<<EOF
aaa
pdg @ sym.checkval~?halt_baddata
EOF
EXPECT=<<EOF
0
EOF
RUN

NAME=arm import veneer tail call resolves to a named call
FILE=bins/elf/bashbot.arm.gcc.O0.elf
CMDS=<<EOF
e r2ghidra.fixups=true
aaa
pdg @ sym.call_weak_fn~__gmon_start__
EOF
EXPECT=<<EOF
    rsym.__gmon_start__();
EOF
RUN

NAME=arm tail call into rsym-flagged local veneer resolves to a named call
FILE=bins/elf/rsym-veneer-arm.so
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF2
e r2ghidra.fixups=true
aaa
pdg @ sym.tail_caller~rsym.local_target
EOF2
EXPECT=<<EOF2
    rsym.local_target();
EOF2
RUN


NAME=windows calling convention on a sysv binary resolves the MSABI proto model
FILE=bins/elf/hello_world
CMDS=<<EOF2
s main
af
afc ms
pdg~MSABI
EOF2
EXPECT=<<EOF2
void MSABI main(int argc,char **argv,char **envp)
EOF2
RUN

NAME=custom calling convention builds a prototype model from r2 cc data
FILE=bins/elf/hello_world
CMDS=<<EOF2
s main
af
afc swift
pdg~r2:swift
EOF2
EXPECT=<<EOF2
void r2:swift main(int argc,char **argv,char **envp)
EOF2
RUN

NAME=arch plugin decodes both languages after switching cpu
FILE=malloc://64
ARGS=-a r2ghidra -b 64
CMDS=<<EOF2
e asm.cpu=arm
wx 298947f9
ao 1~mnemonic
e asm.bits=32
e asm.cpu=x86
wx 90
ao 1~mnemonic
EOF2
EXPECT=<<EOF2
mnemonic: ldr
mnemonic: nop
EOF2
RUN

NAME=arch plugin emits a valid x86 vector register profile
FILE=bins/elf/crackme0x05
ARGS=-a r2ghidra
CMDS=<<EOF2
ar xmm0=0xff
ar xmm0
ar xmm0_qa
EOF2
EXPECT=<<EOF2
0x000000000000000000000000000000ff
0x000000ff
EOF2
RUN
