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

undefined4 main(void)
{
    int32_t var_88h;
    int32_t var_7ch;
    
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    sym.imp.scanf(0x80486b2, &var_7ch);
    sym.check((int32_t)&var_7ch);
    return 0;
}
EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN

NAME=x86_32
FILE=rizin-testbins/elf/crackme0x05
EXPECT=<<EOF
ghidra
x86:LE:32:default:gcc

undefined4 main(void)
{
    int32_t var_88h;
    int32_t var_7ch;
    
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    sym.imp.scanf(0x80486b2, &var_7ch);
    sym.check((int32_t)&var_7ch);
    return 0;
}
EOF
CMDS=<<EOF
s main
af
pdga
e asm.arch
pdgss
pdg
EOF
RUN

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

// WARNING: [rz-ghidra] Detected overlap for variable var_24h

void main(void)
{
    int32_t iVar1;
    int32_t iVar2;
    int64_t iVar3;
    int64_t var_28h;
    int64_t var_20h;
    int64_t var_18h;
    int64_t var_10h;
    
    iVar1 = sym.imp.strlen(0x8d4);
    iVar2 = sym.imp.strlen(0x8da);
    iVar3 = sym.imp.malloc((int64_t)(iVar2 + iVar1 + 1));
    if (iVar3 != 0) {
        sym.imp.strcpy(iVar3, 0x8d4);
        sym.imp.strcat(iVar3, 0x8da);
        sym.imp.puts(iVar3);
        sym.imp.free(iVar3);
    }
    return;
}
EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN

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

// WARNING: Variable defined which should be unmapped: var_8h
// WARNING: Unknown calling convention -- yet parameter storage is locked
// WARNING: [rz-ghidra] Matching calling convention fastcall of function fcn.00001c98 failed, args may be inaccurate.

undefined4 fcn.00001c98(int16_t arg_6h, int16_t arg_4h, int16_t arg_ch)
{
    int16_t *piVar1;
    undefined2 uVar2;
    undefined2 unaff_CS;
    undefined2 unaff_DS;
    undefined4 in_stack_00000008;
    int16_t var_ah;
    int16_t var_8h;
    int16_t var_6h;
    int16_t var_4h;
    
    var_ah = 0x13da;
    do {
        func_0x0000ec24(unaff_CS, var_ah, unaff_DS, 0x401e);
        func_0x0000ec24(0xdee, arg_4h, arg_6h, 0x401e);
        func_0x0000e59a(0xdee, 0x401e);
        var_6h = 0;
        do {
            var_4h._0_1_ = func_0x0000eb82(0xdee);
            if ((char)var_4h == '\r') {
                var_4h._0_1_ = '\n';
            }
            if (var_6h < arg_ch) {
                *(char *)((int16_t)in_stack_00000008 + var_6h) = (char)var_4h;
                var_6h = var_6h + 1;
            }
        } while ((char)var_4h != '\n');
        piVar1 = (int16_t *)0x4022;
        *piVar1 = *piVar1 + -1;
        if (*piVar1 < 0) {
            func_0x0000e4ae(0xdee, 10, 0x401e);
        } else {
            *(undefined *)*(undefined4 *)0x401e = 10;
            *(int16_t *)0x401e = *(int16_t *)0x401e + 1;
        }
        unaff_CS = 0xdee;
        func_0x0000e59a(0xdee, 0x401e);
        var_ah = 0x13db;
        uVar2 = (undefined2)((uint32_t)in_stack_00000008 >> 0x10);
    } while (*(char *)((int16_t)in_stack_00000008 + var_6h + -1) != '\n');
    *(undefined *)((int16_t)in_stack_00000008 + var_6h + -1) = 0;
    return in_stack_00000008;
}
EOF
CMDS=<<EOF
pdgss
s 0x1c98
af
pdg
EOF
RUN

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

// WARNING: [rz-ghidra] Detected overlap for variable var_24h

void main(void)
{
    int32_t iVar1;
    int32_t iVar2;
    int64_t iVar3;
    int64_t var_28h;
    int64_t var_20h;
    int64_t var_18h;
    int64_t var_10h;
    
    iVar1 = sym.imp.strlen(0x8d4);
    iVar2 = sym.imp.strlen(0x8da);
    iVar3 = sym.imp.malloc((int64_t)(iVar2 + iVar1 + 1));
    if (iVar3 != 0) {
        sym.imp.strcpy(iVar3, 0x8d4);
        sym.imp.strcat(iVar3, 0x8da);
        sym.imp.puts(iVar3);
        sym.imp.free(iVar3);
    }
    return;
}
EOF
CMDS=<<EOF
pdgss
s main
af
pdg
EOF
RUN


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

// WARNING: Unknown calling convention -- yet parameter storage is locked
// WARNING: [rz-ghidra] Function fcn.0000080e has no calling convention set, args may be inaccurate.

void fcn.0000080e(int8_t arg_101h)
{
    undefined uVar1;
    uint8_t uVar2;
    
    uVar2 = 0xff;
    do {
        *(undefined *)(uVar2 + 0x3ff) = 0x41;
        uVar1 = *(undefined *)0x824;
        uVar2 = uVar2 - 1;
    } while (uVar2 != 0);
    uVar2 = 0xff;
    do {
        *(undefined *)(uVar2 + 0xd7ff) = uVar1;
        uVar2 = uVar2 - 1;
    } while (uVar2 != 0);
    return;
}
EOF
CMDS=<<EOF
pdgss
s 0x080e
af
pdg
EOF
RUN


NAME=rawptr
FILE=bins/dectest32
EXPECT=<<EOF

undefined4 sym.get_global_array_entry(void)
{
    return *(undefined4 *)0x804c034;
}
--

undefined4 sym.get_global_array_entry(void)
{
    return uRam0804c034;
}
EOF
CMDS=<<EOF
s sym.get_global_array_entry
af
e ghidra.rawptr=1
pdg
echo --
e ghidra.rawptr=0
pdg
EOF
RUN

NAME=global flag
FILE=bins/dectest32
EXPECT=<<EOF

undefined4 sym.get_global_var(void)
{
    return _obj.global_var;
}
--

// WARNING: Globals starting with '_' overlap smaller symbols at the same address

undefined4 sym.get_global_var(void)
{
    return _obj.global_var;
}
EOF
CMDS=<<EOF
s sym.get_global_var
af
e ghidra.rawptr=1
pdg
echo --
e ghidra.rawptr=0
pdg
EOF
RUN

NAME=global variables
FILE=bins/dectest32
EXPECT=<<EOF

uint32_t sym.get_global_var(void)
{
    return global_var;
}
--

uint32_t sym.get_global_var(void)
{
    return global_var;
}
--

uint32_t sym.get_global_array_entry(void)
{
    return global_array[1];
}
--

uint32_t sym.get_global_array_entry(void)
{
    return global_array[1];
}
EOF
CMDS=<<EOF
avga global_var uint32_t @ obj.global_var
avga global_array uint32_t[2] @ obj.global_array
s sym.get_global_var
af
e ghidra.rawptr=1
pdg
echo --
e ghidra.rawptr=0
pdg
echo --
s sym.get_global_array_entry
af
e ghidra.rawptr=1
pdg
echo --
e ghidra.rawptr=0
pdg
EOF
RUN

NAME=function variable annotations
FILE=bins/dectest64
EXPECT=<<EOF
{
  "code": "\n// WARNING: [rz-ghidra] Detected overlap for variable var_28h\n// WARNING: [rz-ghidra] Detected overlap for variable var_14h\n\nundefined8 main(int argc, char **argv)\n{\n    undefined8 uVar1;\n    int64_t in_FS_OFFSET;\n    int64_t var_38h;\n    int64_t var_2ch;\n    int64_t var_10h;\n    \n    var_10h = *(int64_t *)(in_FS_OFFSET + 0x28);\n    var_2ch._0_4_ = argc;\n    sym.Aeropause((int64_t)&var_2ch + 4, argc, argv);\n    uVar1 = 0;\n    if (var_10h != *(int64_t *)(in_FS_OFFSET + 0x28)) {\n        uVar1 = sym.imp.__stack_chk_fail();\n    }\n    return uVar1;\n}\n",
  "annotations": [
    {
      "start": 1,
      "end": 4,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 1,
      "end": 4,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 4,
      "end": 12,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 4,
      "end": 12,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 13,
      "end": 24,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 13,
      "end": 24,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 25,
      "end": 33,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 25,
      "end": 33,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 34,
      "end": 41,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 34,
      "end": 41,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 42,
      "end": 45,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 42,
      "end": 45,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 46,
      "end": 54,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 46,
      "end": 54,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 55,
      "end": 62,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 55,
      "end": 62,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 63,
      "end": 66,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 63,
      "end": 66,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 66,
      "end": 74,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 66,
      "end": 74,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 75,
      "end": 86,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 75,
      "end": 86,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 87,
      "end": 95,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 87,
      "end": 95,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 96,
      "end": 103,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 96,
      "end": 103,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 104,
      "end": 107,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 104,
      "end": 107,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 108,
      "end": 116,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 108,
      "end": 116,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 117,
      "end": 124,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 117,
      "end": 124,
      "type": "syntax_highlight",
      "syntax_highlight": "comment"
    },
    {
      "start": 126,
      "end": 136,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 137,
      "end": 141,
      "type": "function_name",
      "name": "main",
      "offset": 4198782
    },
    {
      "start": 137,
      "end": 141,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 137,
      "end": 141,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 142,
      "end": 145,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 146,
      "end": 150,
      "type": "function_parameter",
      "name": "argc"
    },
    {
      "start": 146,
      "end": 150,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 152,
      "end": 156,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 159,
      "end": 163,
      "type": "function_parameter",
      "name": "argv"
    },
    {
      "start": 159,
      "end": 163,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 171,
      "end": 181,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 182,
      "end": 187,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 182,
      "end": 187,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 193,
      "end": 200,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 201,
      "end": 213,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 201,
      "end": 213,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 219,
      "end": 226,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 227,
      "end": 234,
      "type": "local_variable",
      "name": "var_38h"
    },
    {
      "start": 227,
      "end": 234,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 240,
      "end": 247,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 248,
      "end": 255,
      "type": "local_variable",
      "name": "var_2ch"
    },
    {
      "start": 248,
      "end": 255,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 261,
      "end": 268,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 269,
      "end": 276,
      "type": "local_variable",
      "name": "var_10h"
    },
    {
      "start": 269,
      "end": 276,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 287,
      "end": 294,
      "type": "local_variable",
      "name": "var_10h"
    },
    {
      "start": 287,
      "end": 294,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 295,
      "end": 296,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 297,
      "end": 298,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 299,
      "end": 306,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 310,
      "end": 322,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 310,
      "end": 322,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 323,
      "end": 324,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 325,
      "end": 329,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 287,
      "end": 330,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 336,
      "end": 343,
      "type": "local_variable",
      "name": "var_2ch"
    },
    {
      "start": 336,
      "end": 343,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 343,
      "end": 344,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 350,
      "end": 351,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 352,
      "end": 356,
      "type": "function_parameter",
      "name": "argc"
    },
    {
      "start": 352,
      "end": 356,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 336,
      "end": 356,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 362,
      "end": 375,
      "type": "function_name",
      "name": "sym.Aeropause",
      "offset": 4199038
    },
    {
      "start": 362,
      "end": 375,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 377,
      "end": 384,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 385,
      "end": 386,
      "type": "offset",
      "offset": 4198819
    },
    {
      "start": 386,
      "end": 393,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 394,
      "end": 395,
      "type": "offset",
      "offset": 4198819
    },
    {
      "start": 396,
      "end": 397,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 397,
      "end": 399,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 399,
      "end": 403,
      "type": "function_parameter",
      "name": "argc"
    },
    {
      "start": 399,
      "end": 403,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 403,
      "end": 405,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 405,
      "end": 409,
      "type": "function_parameter",
      "name": "argv"
    },
    {
      "start": 405,
      "end": 409,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 362,
      "end": 410,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 416,
      "end": 421,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 416,
      "end": 421,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 422,
      "end": 423,
      "type": "offset",
      "offset": 4198833
    },
    {
      "start": 424,
      "end": 425,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 416,
      "end": 425,
      "type": "offset",
      "offset": 4198833
    },
    {
      "start": 431,
      "end": 433,
      "type": "offset",
      "offset": 4198851
    },
    {
      "start": 431,
      "end": 433,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 435,
      "end": 442,
      "type": "local_variable",
      "name": "var_10h"
    },
    {
      "start": 435,
      "end": 442,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 443,
      "end": 445,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 446,
      "end": 447,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 448,
      "end": 455,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 459,
      "end": 471,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 459,
      "end": 471,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 472,
      "end": 473,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 474,
      "end": 478,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 491,
      "end": 496,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 491,
      "end": 496,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 497,
      "end": 498,
      "type": "offset",
      "offset": 4198853
    },
    {
      "start": 499,
      "end": 523,
      "type": "function_name",
      "name": "sym.imp.__stack_chk_fail",
      "offset": 4198464
    },
    {
      "start": 499,
      "end": 523,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 491,
      "end": 525,
      "type": "offset",
      "offset": 4198853
    },
    {
      "start": 537,
      "end": 543,
      "type": "offset",
      "offset": 4198859
    },
    {
      "start": 537,
      "end": 543,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 544,
      "end": 549,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 544,
      "end": 549,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 537,
      "end": 549,
      "type": "offset",
      "offset": 4198859
    }
  ]
}
EOF
CMDS=<<EOF
s main
af
pdgj~{}
EOF
RUN

NAME=global variable annotation
FILE=bins/dectest32
EXPECT=<<EOF
{
  "code": "\nundefined4 sym.get_global_array_entry(void)\n{\n    return *(undefined4 *)0x804c034;\n}\n",
  "annotations": [
    {
      "start": 1,
      "end": 11,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 12,
      "end": 38,
      "type": "function_name",
      "name": "sym.get_global_array_entry",
      "offset": 134517184
    },
    {
      "start": 12,
      "end": 38,
      "type": "offset",
      "offset": 134517184
    },
    {
      "start": 12,
      "end": 38,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 39,
      "end": 43,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 51,
      "end": 57,
      "type": "offset",
      "offset": 134517193
    },
    {
      "start": 51,
      "end": 57,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 58,
      "end": 59,
      "type": "offset",
      "offset": 134517187
    },
    {
      "start": 60,
      "end": 70,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 73,
      "end": 82,
      "type": "global_variable",
      "offset": 134529076
    },
    {
      "start": 73,
      "end": 82,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 51,
      "end": 82,
      "type": "offset",
      "offset": 134517193
    }
  ]
}
EOF
CMDS=<<EOF
s sym.get_global_array_entry
af
pdgj~{}
EOF
RUN

NAME=constant variable annotation
FILE=bins/dectest32
EXPECT=<<EOF
{
  "code": "\nvoid sym.PrintAmbassador(int32_t arg_4h)\n{\n    sym.imp.printf(\"Ambassador value: \");\n    switch(arg_4h) {\n    case 0:\n        sym.imp.printf(\"pure\");\n        break;\n    case 1:\n        sym.imp.printf(\"reason\");\n        break;\n    case 2:\n        sym.imp.printf(\"revolution\");\n        break;\n    case 3:\n        sym.imp.printf(\"echoes\");\n        break;\n    case 4:\n        sym.imp.printf(\"wall\");\n        break;\n    default:\n        if (arg_4h == 1000000) {\n            sym.imp.printf(\"million\");\n        }\n        break;\n    case -0x452e541f:\n        break;\n    }\n    sym.imp.putchar(10);\n    return;\n}\n",
  "annotations": [
    {
      "start": 1,
      "end": 5,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 6,
      "end": 25,
      "type": "function_name",
      "name": "sym.PrintAmbassador",
      "offset": 134517281
    },
    {
      "start": 6,
      "end": 25,
      "type": "offset",
      "offset": 134517281
    },
    {
      "start": 6,
      "end": 25,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 26,
      "end": 33,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 34,
      "end": 40,
      "type": "function_parameter",
      "name": "arg_4h"
    },
    {
      "start": 34,
      "end": 40,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 48,
      "end": 62,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 48,
      "end": 62,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 63,
      "end": 83,
      "type": "constant_variable",
      "offset": 134520840
    },
    {
      "start": 63,
      "end": 83,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 48,
      "end": 84,
      "type": "offset",
      "offset": 134517295
    },
    {
      "start": 90,
      "end": 96,
      "type": "offset",
      "offset": 134517332
    },
    {
      "start": 90,
      "end": 96,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 97,
      "end": 103,
      "type": "function_parameter",
      "name": "arg_4h"
    },
    {
      "start": 97,
      "end": 103,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 111,
      "end": 115,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 116,
      "end": 117,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 127,
      "end": 141,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 127,
      "end": 141,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 142,
      "end": 148,
      "type": "constant_variable",
      "offset": 134520859
    },
    {
      "start": 142,
      "end": 148,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 127,
      "end": 149,
      "type": "offset",
      "offset": 134517353
    },
    {
      "start": 159,
      "end": 164,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 159,
      "end": 165,
      "type": "offset",
      "offset": 134517361
    },
    {
      "start": 170,
      "end": 174,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 175,
      "end": 176,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 186,
      "end": 200,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 186,
      "end": 200,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 201,
      "end": 209,
      "type": "constant_variable",
      "offset": 134520864
    },
    {
      "start": 201,
      "end": 209,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 186,
      "end": 210,
      "type": "offset",
      "offset": 134517371
    },
    {
      "start": 220,
      "end": 225,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 220,
      "end": 226,
      "type": "offset",
      "offset": 134517379
    },
    {
      "start": 231,
      "end": 235,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 236,
      "end": 237,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 247,
      "end": 261,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 247,
      "end": 261,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 262,
      "end": 274,
      "type": "constant_variable",
      "offset": 134520871
    },
    {
      "start": 262,
      "end": 274,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 247,
      "end": 275,
      "type": "offset",
      "offset": 134517389
    },
    {
      "start": 285,
      "end": 290,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 285,
      "end": 291,
      "type": "offset",
      "offset": 134517397
    },
    {
      "start": 296,
      "end": 300,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 301,
      "end": 302,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 312,
      "end": 326,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 312,
      "end": 326,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 327,
      "end": 335,
      "type": "constant_variable",
      "offset": 134520882
    },
    {
      "start": 327,
      "end": 335,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 312,
      "end": 336,
      "type": "offset",
      "offset": 134517407
    },
    {
      "start": 346,
      "end": 351,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 346,
      "end": 352,
      "type": "offset",
      "offset": 134517415
    },
    {
      "start": 357,
      "end": 361,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 362,
      "end": 363,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 373,
      "end": 387,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 373,
      "end": 387,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 388,
      "end": 394,
      "type": "constant_variable",
      "offset": 134520889
    },
    {
      "start": 388,
      "end": 394,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 373,
      "end": 395,
      "type": "offset",
      "offset": 134517425
    },
    {
      "start": 405,
      "end": 410,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 405,
      "end": 411,
      "type": "offset",
      "offset": 134517433
    },
    {
      "start": 416,
      "end": 423,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 433,
      "end": 435,
      "type": "offset",
      "offset": 134517341
    },
    {
      "start": 433,
      "end": 435,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 437,
      "end": 443,
      "type": "function_parameter",
      "name": "arg_4h"
    },
    {
      "start": 437,
      "end": 443,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 444,
      "end": 446,
      "type": "offset",
      "offset": 134517334
    },
    {
      "start": 447,
      "end": 454,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 470,
      "end": 484,
      "type": "function_name",
      "name": "",
      "offset": 134516816
    },
    {
      "start": 470,
      "end": 484,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 485,
      "end": 494,
      "type": "constant_variable",
      "offset": 134520894
    },
    {
      "start": 485,
      "end": 494,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 470,
      "end": 495,
      "type": "offset",
      "offset": 134517443
    },
    {
      "start": 515,
      "end": 520,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 526,
      "end": 530,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 531,
      "end": 542,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 552,
      "end": 557,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 552,
      "end": 558,
      "type": "offset",
      "offset": 134517332
    },
    {
      "start": 569,
      "end": 584,
      "type": "function_name",
      "name": "",
      "offset": 134516880
    },
    {
      "start": 569,
      "end": 584,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 585,
      "end": 587,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 569,
      "end": 588,
      "type": "offset",
      "offset": 134517459
    },
    {
      "start": 594,
      "end": 600,
      "type": "offset",
      "offset": 134517469
    },
    {
      "start": 594,
      "end": 600,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 594,
      "end": 600,
      "type": "offset",
      "offset": 134517469
    }
  ]
}
EOF
CMDS=<<EOF
s sym.PrintAmbassador
af
pdgj~{}
EOF
RUN

NAME=aeropause32 (many features combined)
FILE=bins/dectest32
EXPECT=<<EOF

void sym.Aeropause(Bright *bright, int32_t argc, char **argv)
{
    Morning *pMVar1;
    int32_t iVar2;
    
    pMVar1 = (Morning *)sym.imp.malloc(8);
    bright->morning = pMVar1;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    } else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight, data.0804a05c);
        if (iVar2 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        } else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar2 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            } else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar2 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                } else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    // switch table (5 cases) at 0x804a070
    switch(bright->ambassador) {
    case AMBASSADOR_PURE:
        sym.imp.printf("pure");
        break;
    case AMBASSADOR_REASON:
        sym.imp.printf("reason");
        break;
    case AMBASSADOR_REVOLUTION:
        sym.imp.printf("revolution");
        break;
    case AMBASSADOR_ECHOES:
        sym.imp.printf("echoes");
        break;
    case AMBASSADOR_WALL:
        sym.imp.printf("wall");
        break;
    default:
        if (bright->ambassador == AMBASSADOR_MILLION) {
            sym.imp.printf("million");
        }
        break;
    case 0xbad1abe1:
        break;
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}
EOF
CMDS=<<EOF
aaa
to bins/types.h
s sym.Aeropause
afvs 4 bright "Bright *"
afvs 8 argc int32_t
afvs 12 argv "const char **"
pdg
EOF
RUN

NAME=aeropause32-sp (many features combined without bp)
FILE=bins/dectest32-sp
EXPECT=<<EOF

void sym.Aeropause(Bright *bright, int32_t argc, char **argv)
{
    Morning *pMVar1;
    int32_t iVar2;
    size_t in_stack_fffffff4;
    
    pMVar1 = (Morning *)sym.imp.malloc(8);
    bright->morning = pMVar1;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    } else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight, "the  ");
        if (iVar2 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        } else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar2 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            } else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar2 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                } else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    // switch table (5 cases) at 0x804a070
    switch(bright->ambassador) {
    case AMBASSADOR_PURE:
        sym.imp.printf("pure");
        break;
    case AMBASSADOR_REASON:
        sym.imp.printf("reason");
        break;
    case AMBASSADOR_REVOLUTION:
        sym.imp.printf("revolution");
        break;
    case AMBASSADOR_ECHOES:
        sym.imp.printf("echoes");
        break;
    case AMBASSADOR_WALL:
        sym.imp.printf("wall");
        break;
    default:
        if (bright->ambassador == AMBASSADOR_MILLION) {
            sym.imp.printf("million");
        }
        break;
    case 0xbad1abe1:
        break;
    }
    sym.PrintAmbassador(bright->ambassador, in_stack_fffffff4);
    return;
}
EOF
CMDS=<<EOF
aaa
to bins/types.h
f- data.0804a05c
s sym.imp.strcmp
afvs 4 s1 const char *
afvs 8 s2 const char *
s sym.Aeropause
afvs 4 bright "Bright *"
afvs 8 argc int32_t
afvs 12 argv "const char **"
pdg
EOF
RUN

NAME=aeropause64 (many features combined)
FILE=bins/dectest64
EXPECT=<<EOF

// WARNING: [rz-ghidra] Detected overlap for variable var_14h

void sym.Aeropause(Bright *bright, int32_t argc, char **argv)
{
    int32_t iVar1;
    Morning *pMVar2;
    int64_t var_20h;
    void **var_10h;
    
    pMVar2 = (Morning *)sym.imp.malloc(0x10);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    *(char ***)((int64_t)&bright->morning->saved_argv + 4) = argv;
    if (bright->morning->saved_argc < 2) {
        *(undefined4 *)&bright->ambassador = 0;
    } else {
        (bright->window).sunlight = *(char **)(*(int64_t *)((int64_t)&bright->morning->saved_argv + 4) + 8);
        iVar1 = sym.imp.strcmp((bright->window).sunlight, "the  ");
        if (iVar1 == 0) {
            *(undefined4 *)&bright->ambassador = 1;
        } else {
            iVar1 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar1 == 0) {
                *(undefined4 *)&bright->ambassador = 2;
            } else {
                iVar1 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar1 == 0) {
                    *(undefined4 *)&bright->ambassador = 3;
                } else {
                    *(undefined4 *)&bright->ambassador = 1000000;
                }
            }
        }
    }
    // switch table (5 cases) at 0x402088
    switch(*(int32_t *)&bright->ambassador) {
    case 0:
        sym.imp.printf("pure");
        break;
    case 1:
        sym.imp.printf("reason");
        break;
    case 2:
        sym.imp.printf("revolution");
        break;
    case 3:
        sym.imp.printf("echoes");
        break;
    case 4:
        sym.imp.printf("wall");
        break;
    default:
        if (*(int32_t *)&bright->ambassador == 1000000) {
            sym.imp.printf("million");
        }
        break;
    case -0x452e541f:
        break;
    }
    sym.PrintAmbassador((uint64_t)*(uint32_t *)&bright->ambassador);
    return;
}
EOF
CMDS=<<EOF
aaa

# TODO: remove these when rizin can do it automatically
afvr rdi format "const char *" @ sym.imp.printf
afvr rdi size size_t @ sym.imp.malloc
afvr rdi s1 "const char *" @ sym.imp.strcmp
afvr rsi s2 "const char *" @ sym.imp.strcmp

to bins/types.h

s sym.Aeropause
afvr rdi bright "Bright *"
afvr rsi argc int32_t
afvr rdx argv "const char **"
pdg
EOF
RUN

NAME=aeropause64-sp (many features combined without bp)
FILE=bins/dectest64-sp
EXPECT=<<EOF

// WARNING: [rz-ghidra] Detected overlap for variable var_14h
// WARNING: [rz-ghidra] Removing arg arg_14h because it doesn't fit into ProtoModel

void sym.Aeropause(Bright *bright, int32_t argc, char **argv)
{
    int32_t iVar1;
    Morning *pMVar2;
    int64_t var_20h;
    void **var_10h;
    
    pMVar2 = (Morning *)sym.imp.malloc(0x10);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    *(char ***)((int64_t)&bright->morning->saved_argv + 4) = argv;
    if (bright->morning->saved_argc < 2) {
        *(undefined4 *)&bright->ambassador = 0;
    } else {
        (bright->window).sunlight = *(char **)(*(int64_t *)((int64_t)&bright->morning->saved_argv + 4) + 8);
        iVar1 = sym.imp.strcmp((bright->window).sunlight, "the  ");
        if (iVar1 == 0) {
            *(undefined4 *)&bright->ambassador = 1;
        } else {
            iVar1 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar1 == 0) {
                *(undefined4 *)&bright->ambassador = 2;
            } else {
                iVar1 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar1 == 0) {
                    *(undefined4 *)&bright->ambassador = 3;
                } else {
                    *(undefined4 *)&bright->ambassador = 1000000;
                }
            }
        }
    }
    // switch table (5 cases) at 0x402088
    switch(*(int32_t *)&bright->ambassador) {
    case 0:
        sym.imp.printf("pure");
        break;
    case 1:
        sym.imp.printf("reason");
        break;
    case 2:
        sym.imp.printf("revolution");
        break;
    case 3:
        sym.imp.printf("echoes");
        break;
    case 4:
        sym.imp.printf("wall");
        break;
    default:
        if (*(int32_t *)&bright->ambassador == 1000000) {
            sym.imp.printf("million");
        }
        break;
    case -0x452e541f:
        break;
    }
    sym.PrintAmbassador((uint64_t)*(uint32_t *)&bright->ambassador);
    return;
}
EOF
CMDS=<<EOF
aaa

# TODO: remove these when rizin can do it automatically
afvr rdi format "const char *" @ sym.imp.printf
afvr rdi size size_t @ sym.imp.malloc
afvr rdi s1 "const char *" @ sym.imp.strcmp
afvr rsi s2 "const char *" @ sym.imp.strcmp

to bins/types.h

s sym.Aeropause
afvr rdi bright "Bright *"
afvr rsi argc int32_t
afvr rdx argv "const char **"
afvs -0x14 var_14h int32_t
pdg
EOF
RUN


NAME=typedef
BROKEN=1
FILE=bins/dectest32
EXPECT=<<EOF

void sym.Aeropause(BrightPtr bright, Bright *argc, char **argv)
{
    Morning *pMVar1;
    int32_t iVar2;
    
    pMVar1 = (Morning *)sym.imp.malloc(8);
    bright->morning = pMVar1;
    bright->morning->saved_argc = (uint32_t)argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    } else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight, data.0804a05c);
        if (iVar2 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        } else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar2 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            } else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar2 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                } else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    // switch table (5 cases) at 0x804a070
    switch(bright->ambassador) {
    case AMBASSADOR_PURE:
        sym.imp.printf("pure");
        break;
    case AMBASSADOR_REASON:
        sym.imp.printf("reason");
        break;
    case AMBASSADOR_REVOLUTION:
        sym.imp.printf("revolution");
        break;
    case AMBASSADOR_ECHOES:
        sym.imp.printf("echoes");
        break;
    case AMBASSADOR_WALL:
        sym.imp.printf("wall");
        break;
    default:
        if (bright->ambassador == AMBASSADOR_MILLION) {
            sym.imp.printf("million");
        }
        break;
    case 0xbad1abe1:
        break;
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}
--

void sym.Aeropause(BrightTypedefd *bright, int32_t argc, char **argv)
{
    Morning *pMVar1;
    int32_t iVar2;
    
    pMVar1 = (Morning *)sym.imp.malloc(8);
    bright->morning = pMVar1;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    } else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight, data.0804a05c);
        if (iVar2 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        } else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar2 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            } else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar2 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                } else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    // switch table (5 cases) at 0x804a070
    switch(bright->ambassador) {
    case AMBASSADOR_PURE:
        sym.imp.printf("pure");
        break;
    case AMBASSADOR_REASON:
        sym.imp.printf("reason");
        break;
    case AMBASSADOR_REVOLUTION:
        sym.imp.printf("revolution");
        break;
    case AMBASSADOR_ECHOES:
        sym.imp.printf("echoes");
        break;
    case AMBASSADOR_WALL:
        sym.imp.printf("wall");
        break;
    default:
        if (bright->ambassador == AMBASSADOR_MILLION) {
            sym.imp.printf("million");
        }
        break;
    case 0xbad1abe1:
        break;
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}
--

void sym.Aeropause(BrightTypedefdPtr bright, int32_t argc, char **argv)
{
    Morning *pMVar1;
    int32_t iVar2;
    
    pMVar1 = (Morning *)sym.imp.malloc(8);
    bright->morning = pMVar1;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    } else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight, data.0804a05c);
        if (iVar2 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        } else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight, "dark");
            if (iVar2 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            } else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight, "third");
                if (iVar2 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                } else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    // switch table (5 cases) at 0x804a070
    switch(bright->ambassador) {
    case AMBASSADOR_PURE:
        sym.imp.printf("pure");
        break;
    case AMBASSADOR_REASON:
        sym.imp.printf("reason");
        break;
    case AMBASSADOR_REVOLUTION:
        sym.imp.printf("revolution");
        break;
    case AMBASSADOR_ECHOES:
        sym.imp.printf("echoes");
        break;
    case AMBASSADOR_WALL:
        sym.imp.printf("wall");
        break;
    default:
        if (bright->ambassador == AMBASSADOR_MILLION) {
            sym.imp.printf("million");
        }
        break;
    case 0xbad1abe1:
        break;
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}
EOF
CMDS=<<EOF
aaa
to bins/types.h
s sym.Aeropause
afvs 4 bright BrightPtr
afvs 8 argc "Bright *"
afvs 12 argv "const char **"
pdg
echo --
afvs 4 bright "BrightTypedefd *"
afvs 8 argc int32_t
afvs 12 argv "const char **"
pdg
echo --
afvs 4 bright BrightTypedefdPtr
pdg
EOF
RUN

NAME=macos args
FILE=rizin-testbins/mach0/arg
EXPECT=<<EOF

// WARNING: Variable defined which should be unmapped: var_ch
// WARNING: [rz-ghidra] Detected overlap for variable var_1ch

void entry0(void)
{
    char *var_ch;
    
    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)
{
    int32_t var_14h;
    int32_t var_10h;
    int32_t var_ch;
    
    // [10] -r-x section size 200 named .text
    sym.imp.__libc_init();
    // WARNING: Bad instruction - Truncating control flow here
    halt_baddata();
}
EOF
CMDS=<<EOF
s entry0
af
pdg
EOF
RUN

NAME=code printing
FILE=rizin-testbins/elf/crackme0x05
EXPECT=<<EOF

undefined4 main(void)
{
    int32_t var_88h;
    int32_t var_7ch;
    
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    sym.imp.scanf(0x80486b2, &var_7ch);
    sym.check((int32_t)&var_7ch);
    return 0;
}
--
                  |
    0x08048540    |undefined4 main(void)
                  |{
                  |    int32_t var_88h;
                  |    int32_t var_7ch;
                  |    
    0x08048566    |    sym.imp.printf("IOLI Crackme Level 0x05\n");
    0x08048572    |    sym.imp.printf("Password: ");
    0x08048585    |    sym.imp.scanf(0x80486b2, &var_7ch);
    0x0804858a    |    sym.check((int32_t)&var_7ch);
    0x0804859b    |    return 0;
                  |}
--
CCu base64:Jg== @ 0x8048577
CCu base64:bWFpbg== @ 0x8048540
CCu base64:c3ltLmltcC5zY2FuZigweDgwNDg2YjIsICZ2YXJfN2NoKQ== @ 0x8048585
CCu base64:c3ltLmNoZWNrKChpbnQzMl90KSZ2YXJfN2NoKQ== @ 0x8048590
CCu base64:cmV0dXJuIDA= @ 0x804859b
CCu base64:c3ltLmltcC5wcmludGYoIklPTEkgQ3JhY2ttZSBMZXZlbCAweDA1XG4iKQ== @ 0x8048566
CCu base64:c3ltLmltcC5wcmludGYoIlBhc3N3b3JkOiAiKQ== @ 0x8048572
CCu base64:Jg== @ 0x804858a
--
<result><function><function name="main" size="92">
  <localdb main="stack" lock="false">
      <rangelist>
        <range space="stack" first="0x4" last="0x1f7"/>
        <range space="stack" first="0xfff0bdc0" last="0xffffff5f"/>
        <range space="stack" first="0xffffff68" last="0xfffffffb"/>
      </rangelist>
      <symbollist>
        <mapsym>
          </symbol>
          <rangelist/>
        </mapsym>
        <mapsym>
          </symbol>
          <rangelist/>
        </mapsym>
      </symbollist>
    </scope>
  </localdb>
  <ast>
    <varnodes>
    </varnodes>
    <block index="0">
      <rangelist>
        <range space="ram" first="0x8048540" last="0x804859b"/>
      </rangelist>
      <op code="1">
        <seqnum space="ram" offset="0x8048566" uniq="0xe7"/>
      </op>
      <op code="7">
        <seqnum space="ram" offset="0x8048566" uniq="0x80"/>
        <void/>
      </op>
      <op code="1">
        <seqnum space="ram" offset="0x8048572" uniq="0xe8"/>
      </op>
      <op code="7">
        <seqnum space="ram" offset="0x8048572" uniq="0x85"/>
        <void/>
      </op>
      <op code="66">
        <seqnum space="ram" offset="0x8048577" uniq="0xe9"/>
      </op>
      <op code="7">
        <seqnum space="ram" offset="0x8048585" uniq="0x8f"/>
        <void/>
      </op>
      <op code="66">
        <seqnum space="ram" offset="0x804858a" uniq="0xea"/>
      </op>
      <op code="64">
        <seqnum space="ram" offset="0x8048590" uniq="0xeb"/>
      </op>
      <op code="7">
        <seqnum space="ram" offset="0x8048590" uniq="0x96"/>
        <void/>
      </op>
      <op code="1">
        <seqnum space="ram" offset="0x8048595" uniq="0x97"/>
      </op>
      <op code="10">
        <seqnum space="ram" offset="0x804859b" uniq="0x9d"/>
        <void/>
      </op>
    </block>
  </ast>
  <highlist>
    <high repref="0x1a3" class="constant">
    </high>
    <high repref="0x1c1" class="constant">
    </high>
    <high repref="0x2ea" class="constant">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x2eb" class="constant">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x2df" class="constant">
    </high>
    <high repref="0x2e6" class="constant" symref="0x4000010000000000" offset="0">
    </high>
    <high repref="0x2e8" class="constant" symref="0x4000010000000000" offset="0">
    </high>
    <high repref="0x176" class="other">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x190" class="other">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x2e1" class="other" typelock="true">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x2e4" class="other" typelock="true">
      <type name="" size="4" metatype="ptr" core="true">
      </type>
    </high>
    <high repref="0x2ec" class="other">
    </high>
    <high repref="0x1a2" class="other">
    </high>
    <high repref="0x238" class="other" typelock="true">
      <type name="" size="4" metatype="ptr">
        <type name="" size="0" metatype="spacebase" space="stack">
        </type>
      </type>
    </high>
  </highlist>
  <prototype model="__cdecl" extrapop="4">
    <returnsym>
    </returnsym>
  </prototype>
</function>
--
<save_state loadersymbols="false">
  <typegrp intsize="4" longsize="4" enumsize="4" enumsigned="false"/>
  <db>
    <property_changepoint space="ram" offset="0x8048000" val="0x2000"/>
    <property_changepoint space="ram" offset="0x80486bc" val="0x0"/>
    <property_changepoint space="ram" offset="0x804a030" val="0x2000"/>
    <property_changepoint space="ram" offset="0x804a04c" val="0x0"/>
    <property_changepoint space="register" offset="0x1106" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1110" val="0x0"/>
    <property_changepoint space="register" offset="0x1116" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1120" val="0x0"/>
    <property_changepoint space="register" offset="0x1126" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1130" val="0x0"/>
    <property_changepoint space="register" offset="0x1136" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1140" val="0x0"/>
    <property_changepoint space="register" offset="0x1146" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1150" val="0x0"/>
    <property_changepoint space="register" offset="0x1156" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1160" val="0x0"/>
    <property_changepoint space="register" offset="0x1166" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1170" val="0x0"/>
    <property_changepoint space="register" offset="0x1176" val="0x20000000"/>
    <property_changepoint space="register" offset="0x1180" val="0x0"/>
      <rangelist/>
      <symbollist>
        <mapsym>
            <addr space="ram" offset="0x8048540"/>
            <localdb main="stack" lock="false">
                <rangelist>
                  <range space="stack" first="0x4" last="0x1f7"/>
                  <range space="stack" first="0xfff0bdc0" last="0xffffff5f"/>
                  <range space="stack" first="0xffffff68" last="0xfffffffb"/>
                </rangelist>
                <symbollist>
                  <mapsym>
                    </symbol>
                    <addr space="stack" offset="0xffffff84"/>
                    <rangelist/>
                  </mapsym>
                  <mapsym>
                    </symbol>
                    <addr space="stack" offset="0xffffff78"/>
                    <rangelist/>
                  </mapsym>
                </symbollist>
              </scope>
            </localdb>
            <prototype model="__cdecl" extrapop="4">
              <returnsym>
                <addr space="register" offset="0x0" size="4"/>
              </returnsym>
            </prototype>
          </function>
          <addr space="ram" offset="0x8048540"/>
          <rangelist/>
        </mapsym>
        <mapsym>
            <type name="" size="25" metatype="array" arraysize="25">
            </type>
          </symbol>
          <addr space="ram" offset="0x804868e"/>
          <rangelist/>
        </mapsym>
        <mapsym>
            <type name="" size="11" metatype="array" arraysize="11">
            </type>
          </symbol>
          <addr space="ram" offset="0x80486a7"/>
          <rangelist/>
        </mapsym>
        <mapsym>
            <addr space="ram" offset="0x80484c8"/>
            <localdb main="stack" lock="false">
                <rangelist>
                  <range space="stack" first="0x4" last="0x1f7"/>
                  <range space="stack" first="0xfff0bdc0" last="0xffffffff"/>
                </rangelist>
                <symbollist>
                  <mapsym>
                    </symbol>
                    <addr space="stack" offset="0x4"/>
                    <rangelist/>
                  </mapsym>
                  <mapsym>
                    </symbol>
                    <addr space="stack" offset="0xfffffff0"/>
                    <rangelist/>
                  </mapsym>
                  <mapsym>
                    </symbol>
                    <addr space="stack" offset="0xfffffff4"/>
                    <rangelist/>
                  </mapsym>
                </symbollist>
              </scope>
            </localdb>
            <prototype model="__cdecl" extrapop="4" modellock="true">
              <returnsym>
                <addr space="stack" offset="0x0" size="1"/>
              </returnsym>
            </prototype>
          </function>
          <addr space="ram" offset="0x80484c8"/>
          <rangelist/>
        </mapsym>
        <mapsym>
            <addr space="ram" offset="0x8048394"/>
            <localdb main="stack" lock="false">
                <rangelist>
                  <range space="stack" first="0x4" last="0x1f7"/>
                  <range space="stack" first="0xfff0bdc0" last="0xffffffff"/>
                </rangelist>
              </scope>
            </localdb>
            <prototype model="__cdecl" extrapop="4">
              <returnsym>
                <addr space="stack" offset="0x0" size="1"/>
              </returnsym>
            </prototype>
          </function>
          <addr space="ram" offset="0x8048394"/>
          <rangelist/>
        </mapsym>
        <mapsym>
            <addr space="ram" offset="0x8048374"/>
            <localdb main="stack" lock="false">
                <rangelist>
                  <range space="stack" first="0x4" last="0x1f7"/>
                  <range space="stack" first="0xfff0bdc0" last="0xffffffff"/>
                </rangelist>
              </scope>
            </localdb>
            <prototype model="__cdecl" extrapop="4">
              <returnsym>
                <addr space="stack" offset="0x0" size="1"/>
              </returnsym>
            </prototype>
          </function>
          <addr space="ram" offset="0x8048374"/>
          <rangelist/>
        </mapsym>
      </symbollist>
    </scope>
  </db>
  <context_points>
    <context_pointset space="ram" offset="0x0">
      <set name="addrsize" val="0x1"/>
      <set name="bit64" val="0x0"/>
      <set name="highseg" val="0x0"/>
      <set name="instrPhase" val="0x0"/>
      <set name="lockprefx" val="0x0"/>
      <set name="mandover" val="0x0"/>
      <set name="opsize" val="0x1"/>
      <set name="prefix_66" val="0x0"/>
      <set name="prefix_f2" val="0x0"/>
      <set name="prefix_f3" val="0x0"/>
      <set name="repneprefx" val="0x0"/>
      <set name="repprefx" val="0x0"/>
      <set name="reserved" val="0x0"/>
      <set name="rexBprefix" val="0x0"/>
      <set name="rexRprefix" val="0x0"/>
      <set name="rexWRXBprefix" val="0x0"/>
      <set name="rexWprefix" val="0x0"/>
      <set name="rexXprefix" val="0x0"/>
      <set name="rexprefix" val="0x0"/>
      <set name="segover" val="0x0"/>
      <set name="suffix3D" val="0x0"/>
      <set name="vexL" val="0x0"/>
      <set name="vexMMMMM" val="0x0"/>
      <set name="vexMode" val="0x0"/>
      <set name="vexVVVV" val="0x0"/>
      <set name="vexVVVV_r64" val="0x0"/>
      <set name="xacquireprefx" val="0x0"/>
      <set name="xreleaseprefx" val="0x0"/>
    </context_pointset>
    <context_pointset space="register" offset="0x0">
      <set name="addrsize" val="0x0"/>
      <set name="bit64" val="0x0"/>
      <set name="highseg" val="0x0"/>
      <set name="instrPhase" val="0x0"/>
      <set name="lockprefx" val="0x0"/>
      <set name="mandover" val="0x0"/>
      <set name="opsize" val="0x0"/>
      <set name="prefix_66" val="0x0"/>
      <set name="prefix_f2" val="0x0"/>
      <set name="prefix_f3" val="0x0"/>
      <set name="repneprefx" val="0x0"/>
      <set name="repprefx" val="0x0"/>
      <set name="reserved" val="0x0"/>
      <set name="rexBprefix" val="0x0"/>
      <set name="rexRprefix" val="0x0"/>
      <set name="rexWRXBprefix" val="0x0"/>
      <set name="rexWprefix" val="0x0"/>
      <set name="rexXprefix" val="0x0"/>
      <set name="rexprefix" val="0x0"/>
      <set name="segover" val="0x0"/>
      <set name="suffix3D" val="0x0"/>
      <set name="vexL" val="0x0"/>
      <set name="vexMMMMM" val="0x0"/>
      <set name="vexMode" val="0x0"/>
      <set name="vexVVVV" val="0x0"/>
      <set name="vexVVVV_r64" val="0x0"/>
      <set name="xacquireprefx" val="0x0"/>
      <set name="xreleaseprefx" val="0x0"/>
    </context_pointset>
    <tracked_pointset space="ram" offset="0x0">
      <set space="register" offset="0x20a" size="1" val="0x0"/>
    </tracked_pointset>
  </context_points>
  <commentdb/>
  <stringmanage>
    <string>
      <addr space="ram" offset="0x804868e"/>
      <bytes trunc="false">
494f4c4920437261636b6d65204c6576656c2030
  7830350a0050617373776f72
      </bytes>
      <string>
        <addr space="ram" offset="0x80486a7"/>
        <bytes trunc="false">
50617373776f72643a2000257300000000000000
  00ffffffffffffffffffffff
        </bytes>
      </stringmanage>
    </save_state>
--

[38;2;0;55;218mundefined4[0m [38;2;197;15;31mmain[0m([1;38;2;180;0;158mvoid[0m)
{
    [38;2;0;55;218mint32_t[0m [0mvar_88h[0m;
    [38;2;0;55;218mint32_t[0m [0mvar_7ch[0m;
    
    [38;2;197;15;31msym.imp.printf[0m([38;2;193;156;0m"IOLI Crackme Level 0x05\n"[0m);
    [38;2;197;15;31msym.imp.printf[0m([38;2;193;156;0m"Password: "[0m);
    [38;2;197;15;31msym.imp.scanf[0m([38;2;193;156;0m0x80486b2[0m, &[0mvar_7ch[0m);
    [38;2;197;15;31msym.check[0m(([38;2;0;55;218mint32_t[0m)&[0mvar_7ch[0m);
    [1;38;2;180;0;158mreturn[0m [38;2;193;156;0m0[0m;
}
--
                  |
[38;2;0;55;218m[0m    [38;2;19;161;14m0x08048540[0m    |[38;2;0;55;218mundefined4[0m [38;2;197;15;31mmain[0m([1;38;2;180;0;158mvoid[0m)
                  |{
                  |    [38;2;0;55;218mint32_t[0m [0mvar_88h[0m;
                  |    [38;2;0;55;218mint32_t[0m [0mvar_7ch[0m;
                  |    
    [38;2;19;161;14m0x08048566[0m    |    [38;2;197;15;31msym.imp.printf[0m([38;2;193;156;0m"IOLI Crackme Level 0x05\n"[0m);
    [38;2;19;161;14m0x08048572[0m    |    [38;2;197;15;31msym.imp.printf[0m([38;2;193;156;0m"Password: "[0m);
    [38;2;19;161;14m0x08048585[0m    |    [38;2;197;15;31msym.imp.scanf[0m([38;2;193;156;0m0x80486b2[0m, &[0mvar_7ch[0m);
    [38;2;19;161;14m0x0804858a[0m    |    [38;2;197;15;31msym.check[0m(([38;2;0;55;218mint32_t[0m)&[0mvar_7ch[0m);
    [38;2;19;161;14m0x0804859b[0m    |    [1;38;2;180;0;158mreturn[0m [38;2;193;156;0m0[0m;
                  |}
EOF
CMDS=<<EOF
s main
af
e scr.color=0
pdg
echo --
pdgo
echo --
pdg*
echo --
pdgx~!id=,<addr
echo --
pdgd~!id=,protectedMode
echo --
e scr.color=3
pdg
echo --
pdgo
EOF
RUN

NAME=pdgo align
FILE=rizin-testbins/elf/hello_world
ARGS=-B 0x1000000000000000
EXPECT=<<EOF
    0x10000000000007aa    |
    0x10000000000007aa    |// WARNING: [rz-ghidra] Detected overlap for variable var_24h
                          |
    0x10000000000007aa    |void main(void)
                          |{
                          |    int32_t iVar1;
                          |    int32_t iVar2;
                          |    int64_t iVar3;
                          |    int64_t var_28h;
                          |    int64_t var_20h;
                          |    int64_t var_18h;
                          |    int64_t var_10h;
                          |    
    0x10000000000007cf    |    iVar1 = sym.imp.strlen("Hello");
    0x10000000000007de    |    iVar2 = sym.imp.strlen(" r2-folks");
    0x10000000000007f6    |    iVar3 = sym.imp.malloc((int64_t)(iVar2 + iVar1 + 1));
    0x1000000000000804    |    if (iVar3 != 0) {
    0x1000000000000814    |        sym.imp.strcpy(iVar3, "Hello");
    0x1000000000000827    |        sym.imp.strcat(iVar3, " r2-folks");
    0x1000000000000833    |        sym.imp.puts(iVar3);
    0x100000000000083f    |        sym.imp.free(iVar3);
                          |    }
    0x1000000000000846    |    return;
                          |}
EOF
CMDS=<<EOF
s main
af
pdgo
EOF
RUN

NAME=pdgs
FILE==
EXPECT=<<EOF
6502:LE:16:default
65C02:LE:16:default
68000:BE:32:Coldfire
68000:BE:32:MC68020
68000:BE:32:MC68030
68000:BE:32:default
6805:BE:16:default
6809:BE:16:default
80251:BE:24:default
80390:BE:24:default
8048:LE:16:default
8051:BE:16:default
8051:BE:24:mx51
8085:LE:16:default
AARCH64:BE:32:ilp32
AARCH64:BE:64:v8A
AARCH64:LE:32:ilp32
AARCH64:LE:64:AppleSilicon
AARCH64:LE:64:v8A
ARM:BE:32:Cortex
ARM:BE:32:v4
ARM:BE:32:v4t
ARM:BE:32:v5
ARM:BE:32:v5t
ARM:BE:32:v6
ARM:BE:32:v7
ARM:BE:32:v8
ARM:BE:32:v8T
ARM:LE:32:Cortex
ARM:LE:32:v4
ARM:LE:32:v4t
ARM:LE:32:v5
ARM:LE:32:v5t
ARM:LE:32:v6
ARM:LE:32:v7
ARM:LE:32:v8
ARM:LE:32:v8T
ARM:LEBE:32:v7LEInstruction
ARM:LEBE:32:v8LEInstruction
BPF:LE:32:default
CP1600:BE:16:default
CR16C:LE:16:default
DATA:BE:64:default
DATA:LE:64:default
Dalvik:LE:32:DEX_Android10
Dalvik:LE:32:DEX_Android11
Dalvik:LE:32:DEX_Android12
Dalvik:LE:32:DEX_Android13
Dalvik:LE:32:DEX_Base
Dalvik:LE:32:DEX_KitKat
Dalvik:LE:32:DEX_Lollipop
Dalvik:LE:32:DEX_Nougat
Dalvik:LE:32:DEX_Oreo
Dalvik:LE:32:DEX_Pie
Dalvik:LE:32:Marshmallow
Dalvik:LE:32:ODEX_KitKat
Dalvik:LE:32:default
H6309:BE:16:default
HC-12:BE:16:default
HC05:BE:16:M68HC05TB
HC05:BE:16:default
HC08:BE:16:MC68HC908QY4
HC08:BE:16:default
HCS-12:BE:24:default
HCS-12X:BE:24:default
HCS08:BE:16:MC9S08GB60
HCS08:BE:16:default
HCS12:BE:24:default
JVM:BE:32:default
M8C:BE:16:default
MCS96:LE:16:default
MIPS:BE:32:R6
MIPS:BE:32:default
MIPS:BE:32:micro
MIPS:BE:64:64-32R6addr
MIPS:BE:64:64-32addr
MIPS:BE:64:R6
MIPS:BE:64:default
MIPS:BE:64:micro
MIPS:BE:64:micro64-32addr
MIPS:LE:32:R6
MIPS:LE:32:default
MIPS:LE:32:micro
MIPS:LE:64:64-32R6addr
MIPS:LE:64:64-32addr
MIPS:LE:64:R6
MIPS:LE:64:default
MIPS:LE:64:micro
MIPS:LE:64:micro64-32addr
PIC-12:LE:16:PIC-12C5xx
PIC-16:LE:16:PIC-16
PIC-16:LE:16:PIC-16C5x
PIC-16:LE:16:PIC-16F
PIC-17:LE:16:PIC-17C7xx
PIC-18:LE:24:PIC-18
PIC-24E:LE:24:default
PIC-24F:LE:24:default
PIC-24H:LE:24:default
PowerPC:BE:32:4xx
PowerPC:BE:32:MPC8270
PowerPC:BE:32:QUICC
PowerPC:BE:32:default
PowerPC:BE:32:e500
PowerPC:BE:64:64-32addr
PowerPC:BE:64:A2-32addr
PowerPC:BE:64:A2ALT
PowerPC:BE:64:A2ALT-32addr
PowerPC:BE:64:VLE-32addr
PowerPC:BE:64:VLEALT-32addr
PowerPC:BE:64:default
PowerPC:LE:32:4xx
PowerPC:LE:32:QUICC
PowerPC:LE:32:default
PowerPC:LE:32:e500
PowerPC:LE:64:64-32addr
PowerPC:LE:64:A2-32addr
PowerPC:LE:64:A2ALT
PowerPC:LE:64:A2ALT-32addr
PowerPC:LE:64:default
RISCV:LE:32:RV32G
RISCV:LE:32:RV32GC
RISCV:LE:32:RV32I
RISCV:LE:32:RV32IC
RISCV:LE:32:RV32IMC
RISCV:LE:32:default
RISCV:LE:64:RV64G
RISCV:LE:64:RV64GC
RISCV:LE:64:RV64I
RISCV:LE:64:RV64IC
RISCV:LE:64:default
SuperH4:BE:32:default
SuperH4:LE:32:default
SuperH:BE:32:SH-1
SuperH:BE:32:SH-2
SuperH:BE:32:SH-2A
TI_MSP430:LE:16:default
TI_MSP430X:LE:32:default
Toy:BE:32:builder
Toy:BE:32:builder.align2
Toy:BE:32:default
Toy:BE:32:posStack
Toy:BE:32:wordSize2
Toy:BE:64:default
Toy:BE:64:harvard
Toy:LE:32:builder
Toy:LE:32:builder.align2
Toy:LE:32:default
Toy:LE:32:wordSize2
Toy:LE:64:default
V850:LE:32:default
avr32:BE:32:default
avr8:LE:16:atmega256
avr8:LE:16:default
avr8:LE:16:extended
avr8:LE:24:xmega
dsPIC30F:LE:24:default
dsPIC33C:LE:24:default
dsPIC33E:LE:24:default
dsPIC33F:LE:24:default
eBPF:LE:64:default
pa-risc:BE:32:default
sparc:BE:32:default
sparc:BE:64:default
tricore:LE:32:default
tricore:LE:32:tc172x
tricore:LE:32:tc176x
tricore:LE:32:tc29x
x86:LE:16:Protected Mode
x86:LE:16:Real Mode
x86:LE:32:System Management Mode
x86:LE:32:default
x86:LE:64:compat32
x86:LE:64:default
z180:LE:16:default
z182:LE:16:default
z80:LE:16:default
z8401x:LE:16:default
EOF
CMDS=<<EOF
pdgs
EOF
RUN

NAME=pdgsd
FILE=rizin-testbins/elf/crackme0x05
EXPECT=<<EOF
push ebp
mov ebp, esp
sub esp, 0x88
and esp, 0xfffffff0
mov eax, 0
add eax, 0xf
add eax, 0xf
shr eax, 4
-----
0x08048540: PUSH EBP
    (unique,0x9b80,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
0x08048541: MOV EBP,ESP
    EBP = COPY ESP
0x08048543: SUB ESP,0x88
    CF = INT_LESS ESP, 0x88
    OF = INT_SBORROW ESP, 0x88
    ESP = INT_SUB ESP, 0x88
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0xdd00,4) = INT_AND ESP, 0xff
    (unique,0xdd80,1) = POPCOUNT (unique,0xdd00,4)
    (unique,0xde00,1) = INT_AND (unique,0xdd80,1), 0x1
    PF = INT_EQUAL (unique,0xde00,1), 0x0
0x08048549: AND ESP,0xfffffff0
    CF = COPY 0x0
    OF = COPY 0x0
    ESP = INT_AND ESP, 0xfffffff0
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0xdd00,4) = INT_AND ESP, 0xff
    (unique,0xdd80,1) = POPCOUNT (unique,0xdd00,4)
    (unique,0xde00,1) = INT_AND (unique,0xdd80,1), 0x1
    PF = INT_EQUAL (unique,0xde00,1), 0x0
0x0804854c: MOV EAX,0x0
    EAX = COPY 0x0
0x08048551: ADD EAX,0xf
    CF = INT_CARRY EAX, 0xf
    OF = INT_SCARRY EAX, 0xf
    EAX = INT_ADD EAX, 0xf
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0xdd00,4) = INT_AND EAX, 0xff
    (unique,0xdd80,1) = POPCOUNT (unique,0xdd00,4)
    (unique,0xde00,1) = INT_AND (unique,0xdd80,1), 0x1
    PF = INT_EQUAL (unique,0xde00,1), 0x0
0x08048554: ADD EAX,0xf
    CF = INT_CARRY EAX, 0xf
    OF = INT_SCARRY EAX, 0xf
    EAX = INT_ADD EAX, 0xf
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0xdd00,4) = INT_AND EAX, 0xff
    (unique,0xdd80,1) = POPCOUNT (unique,0xdd00,4)
    (unique,0xde00,1) = INT_AND (unique,0xdd80,1), 0x1
    PF = INT_EQUAL (unique,0xde00,1), 0x0
0x08048557: SHR EAX,0x4
    (unique,0x3e780,4) = INT_AND 0x4, 0x1f
    (unique,0x3e800,4) = COPY EAX
    EAX = INT_RIGHT EAX, (unique,0x3e780,4)
    (unique,0x11200,1) = INT_NOTEQUAL (unique,0x3e780,4), 0x0
    (unique,0x11280,4) = INT_SUB (unique,0x3e780,4), 0x1
    (unique,0x11300,4) = INT_RIGHT (unique,0x3e800,4), (unique,0x11280,4)
    (unique,0x11380,4) = INT_AND (unique,0x11300,4), 0x1
    (unique,0x11480,1) = INT_NOTEQUAL (unique,0x11380,4), 0x0
    (unique,0x11500,1) = BOOL_NEGATE (unique,0x11200,1)
    (unique,0x11580,1) = INT_AND (unique,0x11500,1), CF
    (unique,0x11600,1) = INT_AND (unique,0x11200,1), (unique,0x11480,1)
    CF = INT_OR (unique,0x11580,1), (unique,0x11600,1)
    (unique,0x11780,1) = INT_EQUAL (unique,0x3e780,4), 0x1
    (unique,0x11880,1) = INT_SLESS (unique,0x3e800,4), 0x0
    (unique,0x11900,1) = BOOL_NEGATE (unique,0x11780,1)
    (unique,0x11980,1) = INT_AND (unique,0x11900,1), OF
    (unique,0x11a00,1) = INT_AND (unique,0x11780,1), (unique,0x11880,1)
    OF = INT_OR (unique,0x11980,1), (unique,0x11a00,1)
    (unique,0xdf80,1) = INT_NOTEQUAL (unique,0x3e780,4), 0x0
    (unique,0xe080,1) = INT_SLESS EAX, 0x0
    (unique,0xe100,1) = BOOL_NEGATE (unique,0xdf80,1)
    (unique,0xe180,1) = INT_AND (unique,0xe100,1), SF
    (unique,0xe200,1) = INT_AND (unique,0xdf80,1), (unique,0xe080,1)
    SF = INT_OR (unique,0xe180,1), (unique,0xe200,1)
    (unique,0xe380,1) = INT_EQUAL EAX, 0x0
    (unique,0xe400,1) = BOOL_NEGATE (unique,0xdf80,1)
    (unique,0xe480,1) = INT_AND (unique,0xe400,1), ZF
    (unique,0xe500,1) = INT_AND (unique,0xdf80,1), (unique,0xe380,1)
    ZF = INT_OR (unique,0xe480,1), (unique,0xe500,1)
    (unique,0xe600,4) = INT_AND EAX, 0xff
    (unique,0xe680,1) = POPCOUNT (unique,0xe600,4)
    (unique,0xe700,1) = INT_AND (unique,0xe680,1), 0x1
    (unique,0xe800,1) = INT_EQUAL (unique,0xe700,1), 0x0
    (unique,0xe880,1) = BOOL_NEGATE (unique,0xdf80,1)
    (unique,0xe900,1) = INT_AND (unique,0xe880,1), PF
    (unique,0xe980,1) = INT_AND (unique,0xdf80,1), (unique,0xe800,1)
    PF = INT_OR (unique,0xe900,1), (unique,0xe980,1)
EOF
CMDS=<<EOF
s main
pi 8
echo -----
pdgsd 8~!STORE
EOF
RUN

NAME=comments
FILE=rizin-testbins/elf/crackme0x05
EXPECT=<<EOF

undefined4 main(void)
{
    int32_t var_88h;
    int32_t var_7ch;
    
    // main starts here
    // printf call here
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
    // scanf call here
    sym.imp.scanf(0x80486b2, &var_7ch);
    sym.check((int32_t)&var_7ch);
    // main returns here
    return 0;
}
EOF
CMDS=<<EOF
CCu base64:bWFpbiBzdGFydHMgaGVyZQ== @ 0x08048540
CCu base64:cHJpbnRmIGNhbGwgaGVyZQ== @ 0x08048566
CCu base64:bWFpbiByZXR1cm5zIGhlcmU= @ 0x0804859b
CCu base64:bm90aGluZyB0byBzZWUgaGVyZQ== @ 0x0804859c
CCu base64:c2NhbmYgY2FsbCBoZXJl @ 0x08048585
s main
af
pdg
EOF
RUN

NAME=comment-function_name-offset
FILE=rizin-testbins/elf/crackme0x05
EXPECT=<<EOF
                  |
    0x08048540    |undefined4 main(void)
                  |{
                  |    int32_t var_88h;
                  |    int32_t var_7ch;
                  |    
    0x08048540    |    // main starts here
    0x08048566    |    // printf call here
    0x08048566    |    sym.imp.printf("IOLI Crackme Level 0x05\n");
    0x08048572    |    sym.imp.printf("Password: ");
    0x08048585    |    // scanf call here
    0x08048585    |    sym.imp.scanf(0x80486b2, &var_7ch);
    0x0804858a    |    sym.check((int32_t)&var_7ch);
    0x0804859b    |    // main returns here
    0x0804859b    |    return 0;
                  |}
EOF
CMDS=<<EOF
CCu base64:bWFpbiBzdGFydHMgaGVyZQ== @ 0x08048540
CCu base64:cHJpbnRmIGNhbGwgaGVyZQ== @ 0x08048566
CCu base64:bWFpbiByZXR1cm5zIGhlcmU= @ 0x0804859b
CCu base64:bm90aGluZyB0byBzZWUgaGVyZQ== @ 0x0804859c
CCu base64:c2NhbmYgY2FsbCBoZXJl @ 0x08048585
s main
af
pdgo
EOF
RUN

NAME=recursive type
FILE=bins/rec
CMDS=<<EOF
to bins/types_rec.h
aaa
s sym.KillList
afvt arg1 LL
afvt ptr LL
pdg
EOF
EXPECT=<<EOF

void sym.KillList(LL arg1)
{
    LL pLVar1;
    LL ptr;
    int64_t var_10h;
    
    ptr = arg1;
    while (ptr != (LL)0x0) {
        pLVar1 = ptr->next;
        sym.imp.free(ptr);
        ptr = pLVar1;
    }
    return;
}
EOF
RUN

NAME=strings
FILE=bins/strings
CMDS=<<EOF
aaa
afvt arg1 "char16_t *" @ sym.use_utf16
pdg @ main
EOF
EXPECT=<<EOF

undefined8 main(void)
{
    sym.imp.puts("Hello this is a regular string\n");
    sym.use_utf16(L"Henlo completely obsolete encoding\n");
    sym.imp.fputws(L"This is a wiiiiiiiiiiiide string\n", _reloc.stdout);
    return 0;
}
EOF
RUN


NAME=show noreturn
FILE=rizin-testbins/elf/ioli/crackme0x07
CMDS=<<EOF
aaa
s sym.imp.exit
pdg
EOF
EXPECT=<<EOF

void sym.imp.exit noreturn (void)
{
    // WARNING: Could not recover jumptable at 0x080483e8. Too many branches
    // WARNING: Treating indirect jump as call
    (*_reloc.exit)();
    return;
}
EOF
RUN

NAME=callables and atomic (jni)
FILE=rizin-testbins/elf/jni/jniO0-arm64
CMDS=<<EOF
to bins/jni-simplified.h
aaa
s sym.Java_JNIFoo_nativeFoo
afvr x0 env JNIEnv *
afvr x1 obj jobject
pdg
EOF
EXPECT=<<EOF

jstring sym.Java_JNIFoo_nativeFoo(JNIEnv *env, jobject obj)
{
    int64_t iVar1;
    jstring pvVar2;
    
    iVar1 = sym.imp.malloc(0x1e);
    if (iVar1 == 0) {
        pvVar2 = (jstring)0x0;
    } else {
        sym.imp.memset(iVar1, 0, 0x1e);
        pvVar2 = (*(*env)->NewStringUTF)(env, "foo: Test program of JNI.\\n");
        sym.imp.free(0x650);
    }
    return pvVar2;
}
EOF
RUN

NAME=readonlypropagate (objc)
FILE=rizin-testbins/mach0/hello-macos-arm64
CMDS=<<EOF
aaa
s main
echo ------------ with propagation
e ghidra.ropropagate
pdg
echo ------------ without propagation
e ghidra.ropropagate=0
pdg
EOF
EXPECT=<<EOF
------------ with propagation
true

// WARNING: Variable defined which should be unmapped: var_10h
// WARNING: Variable defined which should be unmapped: var_8h
// WARNING: [rz-ghidra] Failed to get address for var argc
// WARNING: [rz-ghidra] Failed to get address for var argv
// WARNING: [rz-ghidra] Detected overlap for variable var_14h
// WARNING: [rz-ghidra] Detected overlap for variable var_2ch

int64_t dbg.main(void)
{
    undefined4 uVar1;
    int64_t iVar2;
    int64_t arg1;
    int64_t arg2;
    int64_t var_50h;
    int64_t var_48h;
    int64_t var_40h;
    int64_t var_38h;
    int64_t var_28h;
    int64_t var_20h;
    int64_t var_10h;
    int64_t var_8h;
    
    arg1 = fcn.100003d9c();
    iVar2 = arg1;
    arg1._0_4_ = (*fcns[1])(&a);
    uVar1 = (undefined4)arg1;
    section.1.__TEXT.__stubs("");
    arg1 = fcn.100003d84(sym.class_Test);
    fcn.100003da8(arg1, "methodWithoutArgs");
    fcn.100003da8(arg1, "methodWithOneArg:", 0x7b);
    fcn.100003da8(arg1, "methodWithTwoArgs:secondArg:", 0x539, uVar1);
    fcn.100003da8(arg1, "methodWithReturn");
    section.1.__TEXT.__stubs("");
    fcn.100003d90(iVar2);
    arg1 = 0;
    return arg1;
}
------------ without propagation

// WARNING: Variable defined which should be unmapped: var_10h
// WARNING: Variable defined which should be unmapped: var_8h
// WARNING: [rz-ghidra] Failed to get address for var argc
// WARNING: [rz-ghidra] Failed to get address for var argv
// WARNING: [rz-ghidra] Detected overlap for variable var_14h
// WARNING: [rz-ghidra] Detected overlap for variable var_2ch

int64_t dbg.main(void)
{
    undefined4 uVar1;
    int64_t iVar2;
    int64_t arg1;
    int64_t arg2;
    int64_t var_50h;
    int64_t var_48h;
    int64_t var_40h;
    int64_t var_38h;
    int64_t var_28h;
    int64_t var_20h;
    int64_t var_10h;
    int64_t var_8h;
    
    arg1 = fcn.100003d9c();
    iVar2 = arg1;
    arg1._0_4_ = (*fcns[1])(&a);
    uVar1 = (undefined4)arg1;
    section.1.__TEXT.__stubs("");
    arg1 = fcn.100003d84(*(undefined8 *)0x100008110);
    fcn.100003da8(arg1, *(undefined8 *)0x1000080f0);
    fcn.100003da8(arg1, *(undefined8 *)0x1000080f8, 0x7b);
    fcn.100003da8(arg1, *(undefined8 *)0x100008100, 0x539, uVar1);
    fcn.100003da8(arg1, *(undefined8 *)0x100008108);
    section.1.__TEXT.__stubs("");
    fcn.100003d90(iVar2);
    arg1 = 0;
    return arg1;
}
EOF
RUN

NAME=reloc target functions
FILE=rizin-testbins/elf/linux-example-x86-32.ko
CMDS=<<EOF
s sym.ko_example_init
af
pdg
EOF
EXPECT=<<EOF

undefined4 sym.ko_example_init(void)
{
    // [04] -r-x section size 22 named .init.text
    __fentry__();
    printk("Hello, Rizin!\n");
    return 0;
}
EOF
RUN

NAME=realname and multiple flags at function
FILE=rizin-testbins/mach0/hello-macos-arm64-objc-stubs-stripped
CMDS=<<EOF
e asm.flags.real=1
aaa
pdg @ 0x100003ae8
EOF
EXPECT=<<EOF

// WARNING: Variable defined which should be unmapped: var_10h
// WARNING: [rz-ghidra] Detected overlap for variable var_2ch

void method.Test.methodWithTwoArgs:secondArg:(int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4)
{
    int32_t var_2ch;
    int64_t var_28h;
    int64_t var_10h;
    
    var_2ch = (int32_t)arg4;
    if (var_2ch < (int32_t)arg3) {
        var_2ch = (int32_t)arg3;
    }
    *(int32_t *)(arg1 + 8) = var_2ch;
    NSLog(__CFConstantStringClassReference);
    return;
}
EOF
RUN

NAME=Generated function names without rizin functions
FILE=rizin-testbins/mach0/hello-macos-arm64-objc-stubs-stripped
CMDS=<<EOF
aalos
s main
aF
pdg @e:asm.flags.real=1
pdg @e:asm.flags.real=0
EOF
EXPECT=<<EOF

// WARNING: Variable defined which should be unmapped: var_10h

undefined8 main(void)
{
    undefined4 uVar1;
    undefined8 uVar2;
    undefined8 uVar3;
    int64_t var_50h;
    int64_t var_48h;
    int64_t var_40h;
    int64_t var_38h;
    int64_t var_10h;
    
    uVar2 = objc_autoreleasePoolPush();
    uVar1 = (**(code **)0x100008158)(0x100008148);
    NSLog(__CFConstantStringClassReference);
    uVar3 = objc_alloc_init(0x100008120);
    objc_msgSend$methodWithoutArgs(uVar3, var_48h);
    objc_msgSend$methodWithOneArg:(uVar3, var_48h, 0x7b);
    objc_msgSend$methodWithTwoArgs:secondArg:(uVar3, var_48h, 0x539, uVar1);
    objc_msgSend$methodWithReturn(uVar3, var_48h);
    NSLog(__CFConstantStringClassReference);
    objc_autoreleasePoolPop(uVar2);
    return 0;
}

// WARNING: Variable defined which should be unmapped: var_10h

undefined8 main(void)
{
    undefined4 uVar1;
    undefined8 uVar2;
    undefined8 uVar3;
    int64_t var_50h;
    int64_t var_48h;
    int64_t var_40h;
    int64_t var_38h;
    int64_t var_10h;
    
    uVar2 = sym.imp.objc_autoreleasePoolPush();
    uVar1 = (**(code **)0x100008158)(0x100008148);
    sym.imp.NSLog(reloc.__CFConstantStringClassReference.1000040a8);
    uVar3 = sym.imp.objc_alloc_init(0x100008120);
    stub.objc_msgSend_methodWithoutArgs(uVar3, var_48h);
    stub.objc_msgSend_methodWithOneArg:(uVar3, var_48h, 0x7b);
    stub.objc_msgSend_methodWithTwoArgs:secondArg:(uVar3, var_48h, 0x539, uVar1);
    stub.objc_msgSend_methodWithReturn(uVar3, var_48h);
    sym.imp.NSLog(reloc.__CFConstantStringClassReference.1000040c8);
    sym.imp.objc_autoreleasePoolPop(uVar2);
    return 0;
}
EOF
RUN

NAME=fixup shared return call to relocs
FILE=bins/sharedReturn.o
CMDS=<<EOF
aaa
pdg @ sym.main
EOF
EXPECT=<<EOF

undefined8 sym.main(void)
{
    int32_t iVar1;
    undefined8 uVar2;
    
    // [04] -r-x section size 31 named .text.startup
    iVar1 = getNum();
    if (iVar1 < 3) {
        return 0;
    }
    uVar2 = calc(iVar1, 2);
    return uVar2;
}
EOF
RUN