NAME=td anonymous struct in typedef
FILE=--
CMDS=<<EOF
"td typedef struct {int a;} Foo;"
"td typedef struct { char *hello; int world[]; } Bar;"
ts~Foo,Bar
ts Foo
ts Bar
EOF
EXPECT=<<EOF
Bar
Foo
pf d a
pf zd hello world
EOF
RUN

NAME=ts add and delete
FILE=--
CMDS=<<EOF
t-*
?e --
"td typedef struct {int a;} Foo;"
ts
ts Foo
ts-Foo
?e --
ts~Foo
EOF
EXPECT=<<EOF
--
Foo
--
EOF
RUN

NAME=typelinks
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
wx 41574156415541544989f4555389fd4881eca8030000488b3e64488b042528000000488984249803000031c0e82fb30000488d35d54e0100bf0600000
e asm.comments=false
s 2
tl short
s +6
tl int
s 0
pd 8
EOF
EXPECT=<<EOF
            0x00000000      4157           push r15
(short)
0x00000002 = 0x5641
            0x00000004      4155           push r13
            0x00000006      4154           push r12
(int)
0x00000008 = 0x55f48949
            0x0000000c      53             push rbx
            0x0000000d      89fd           mov ebp, edi
            0x0000000f      4881eca803..   sub rsp, 0x3a8
EOF
RUN

NAME=typelinks 2
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
wx 48656c6c341248656c6c6f00000000000000000048656c6c6f0000000000000000009090
tk WORD=type
tk type.WORD=w
tk type.WORD.size=16
tk VbHeader=struct
tk struct.VbHeader=szVbMagic,wRuntimeBuild,szLangDll,szSecLangDll
tk struct.VbHeader.szVbMagic=char,0,4
tk struct.VbHeader.wRuntimeBuild=WORD,4,0
tk struct.VbHeader.szLangDll=char,6,14
tk struct.VbHeader.szSecLangDll=char,20,14
tl VbHeader @ 0x00
pd 3
EOF
EXPECT=<<EOF
(VbHeader)
     szVbMagic : 0x00000000 = "Hell"
 wRuntimeBuild : 0x00000004 = 0x1234
     szLangDll : 0x00000006 = "Hello"
  szSecLangDll : 0x00000014 = "Hello"
            0x00000022      90             nop
            0x00000023      90             nop
EOF
RUN

NAME=List type links
CMDS=<<EOF
tl int = 0x4
w test @ 0x10
tl char * = 0x10
tl
EOF
EXPECT=<<EOF
0x00000004 = int
0x00000010 = char *
EOF
RUN

NAME=List readable type links
CMDS=<<EOF
tl int
wB -1
tl int = 0x8
w test @ 0x10
tl char * = 0x10
tll
EOF
EXPECT=<<EOF
(int)
0x00000000 = -1
(int)
0x00000008 = 0x00000000
(char *)
0x00000010 = "test"
EOF
RUN

NAME=jni and SoP
FILE=bins/elf/libverifyPass.so
CMDS=<<EOF
e anal.vars.stackname=true
e asm.lines.bb = false
e asm.lines.jmp = false
e io.cache=false
e io.cache.read=false
wc-*
aa
s sym.Java_com_app_ndh_NDHActivity_print
to bins/headers/jni.h
td struct NULL { }
tl JNINativeInterface = 0x464c457f
tl NULL = 0
pdf~JNINativeInterface
pdr~JNI?
EOF
EXPECT=<<EOF
| ; var struct JNINativeInterface @ sp+0x12c
| 0x00000f74      4b93           str r3, [JNINativeInterface]
| 0x00000f76      039b           ldr r3, [var_134h]                    ; JNINativeInterface.reserved0
| 0x00000f7e      d358           ldr r3, [r2, r3]                      ; JNINativeInterface.GetStringUTFChars
| 0x00000f82      019a           ldr r2, [var_13ch]                    ; JNINativeInterface.reserved0
| 0x0000100e      d358           ldr r3, [r2, r3]                      ; JNINativeInterface.GetStringLength
| 0x00001012      019a           ldr r2, [var_13ch]                    ; JNINativeInterface.reserved0
| 0x00001066      d258           ldr r2, [r2, r3]                      ; JNINativeInterface.NewStringUTF
| 0x00001114      d258           ldr r2, [r2, r3]                      ; JNINativeInterface.NewStringUTF
| 0x0000112e      d258           ldr r2, [r2, r3]                      ; JNINativeInterface.NewStringUTF
| 0x00001144      4b9a           ldr r2, [JNINativeInterface]
| 0x00001148      9a42           cmp r2, r3                            ; JNINativeInterface.reserved0
12
EOF
RUN

NAME=t
FILE=-
CMDS=t~char,double,float,int,long,short,size,uid,void # basic universal types
EXPECT=<<EOF
char
char *
char **
double
float
int
int16_t
int32_t
int64_t
int8_t
long
long long
short
size_t
uid_t
uint16_t
uint32_t
uint64_t
uint8_t
unsigned char
unsigned int
unsigned short
void *
EOF
RUN

NAME=t <type>
FILE=-
CMDS=<<EOF
t int
t-*
t int
EOF
EXPECT=<<EOF
pf d
EOF
EXPECT_ERR=<<EOF
ERROR: Cannot find 'int' type
EOF
RUN

NAME=t-enum
FILE=-
CMDS=<<EOF
td enum pe_machine { IMAGE_FILE_MACHINE_IA64=0x200, IMAGE_FILE_MACHINE_I386=0x14c };
te~?pe_machine
t-pe_machine
te~?pe_machine
EOF
EXPECT=<<EOF
1
0
EOF
RUN

NAME=t-struct
FILE=-
CMDS=<<EOF
t-*
"td struct three_elements{int x; char y; float z;}"
t-three_elements
ts~?
EOF
EXPECT=<<EOF
0
EOF
RUN

NAME=t-union
FILE=-
CMDS=<<EOF
"td union xoo{int x; int y; int z;}"
tk*~union
t-xoo
EOF
EXPECT=<<EOF
union.xoo=x,y,z
union.xoo.x=int32_t,0,0
union.xoo.x.meta=0
union.xoo.y=int32_t,0,0
union.xoo.y.meta=0
union.xoo.z=int32_t,0,0
union.xoo.z.meta=0
xoo=union
EOF
RUN

NAME=typedef
FILE=-
CMDS=<<EOF
"td typedef int Abracadabra"
t-Abracadabra
t~?Abracadabra
EOF
EXPECT=<<EOF
0
EOF
RUN

NAME=t-*
FILE=-
CMDS=<<EOF
td enum pe_machine { IMAGE_FILE_MACHINE_IA64=0x200, IMAGE_FILE_MACHINE_I386=0x14c };
t-*
t
EOF
EXPECT=<<EOF
EOF
RUN

NAME=teb
FILE=-
CMDS=<<EOF
td enum pe_machine { IMAGE_FILE_MACHINE_IA64=0x200, IMAGE_FILE_MACHINE_I386=0x14c };
teb pe_machine IMAGE_FILE_MACHINE_I386
EOF
EXPECT=<<EOF
0x14c
EOF
RUN

NAME=te
FILE=-
CMDS=<<EOF
td enum pe_machine { IMAGE_FILE_MACHINE_IA64=0x200, IMAGE_FILE_MACHINE_I386=0x14c };
te pe_machine 0x14c
EOF
EXPECT=<<EOF
IMAGE_FILE_MACHINE_I386
EOF
RUN

NAME=tt
FILE=-
CMDS=<<EOF
td typedef char FILE_NAME;
tt FILE_NAME
"td typedef bool FLAG;"
tt FLAG
EOF
EXPECT=<<EOF
char
bool
EOF
RUN

NAME=td struct
FILE=-
CMDS=<<EOF
t-*
"td struct test_struct{int x;int y;};"
ts~?test_struct
EOF
EXPECT=<<EOF
1
EOF
RUN

NAME=enum32
FILE=-
CMDS=<<EOF
"td enum v { t=0x123, p=0x321 };"
te~?
tk v
tk enum.v.t
tk enum.v.p
EOF
EXPECT=<<EOF
1
enum
0x123
0x321
EOF
RUN

NAME=enum64
FILE=-
CMDS=<<EOF
"td enum v { t=0x8000000000000001, p=0x8000000000000008 };"
te~?
tk enum.v.t
tk enum.v.p
EOF
EXPECT=<<EOF
1
0x8000000000000001
0x8000000000000008
EOF
RUN

NAME=to error.h
FILE=-
CMDS=<<EOF
to bins/other/error.h
t~char,double,float,int,long,short,size,uid,void # basic universal types
t~addr,date,dox,name
ts~addr,date,dox,name
t addr
EOF
EXPECT_ERR=<<EOF
ERROR: bins/other/error.h:2: warning: #error your compiler doesn't have support to my API

EOF
EXPECT=<<EOF
char
char *
char **
double
float
int
int16_t
int32_t
int64_t
int8_t
long
long long
short
size_t
uid_t
uint16_t
uint32_t
uint64_t
uint8_t
unsigned char
unsigned int
unsigned short
void *
addr
addr_t
date
date_t
dox
dox_t
name
name_t
pf [127]z[40]zd street city zip
EOF
RUN

NAME=to test.h
FILE=-
CMDS=<<EOF
to bins/other/test.h
t~char,double,float,int,long,short,size,uid,void # basic universal types
ts~addr,date,dox,name
t addr
EOF
EXPECT=<<EOF
char
char *
char **
double
float
int
int16_t
int32_t
int64_t
int8_t
long
long long
short
size_t
uid_t
uint16_t
uint32_t
uint64_t
uint8_t
unsigned char
unsigned int
unsigned short
void *
addr
addr_t
date
date_t
dox
dox_t
name
name_t
pf [127]z[40]zd street city zip
EOF
RUN

NAME=t*
FILE=-
CMDS=<<EOF
t-*
tk a=b
t*
EOF
EXPECT=<<EOF
"tk a=b"
EOF
RUN

NAME=tp
FILE=-
CMDS=<<EOF
"td struct person { int age; char name[10]; }"
s 4
w Carlos
s 0
wx 13
tp person @ 0x0
EOF
EXPECT=<<EOF
  age : 0x00000000 = 0x00000013
 name : 0x00000004 = "Carlos"
EOF
RUN

NAME=unions
FILE=-
CMDS=<<EOF
"td union x{float a;int b;}"
tu
EOF
EXPECT=<<EOF
x
EOF
RUN

NAME=Types not reloaded when arch is the same
FILE=-
CMDS=<<EOF
e asm.arch=x86
e anal.arch=x86
e asm.bits=32
t-*
tk a=b
e asm.arch=x68
e asm.bits=32
e anal.arch=x86
tk a
EOF
EXPECT=<<EOF
b
EOF
RUN

NAME=td twice
FILE=-
CMDS=<<EOF
"td int foo(int bar);"
"td int foo(int bar);"
tk~foo
EOF
EXPECT_ERR=<<EOF
EOF
EXPECT=<<EOF
foo=func
func.foo.arg.0=int32_t,bar
func.foo.args=1
func.foo.cc=cdecl
func.foo.ret=int32_t
EOF
RUN

NAME=struct of struct with ts and pf
FILE=-
CMDS=<<EOF
"td struct bar { int a; int b; };"
"td struct foo { int x; struct bar moo; };"
ts foo
.ts foo
EOF
EXPECT=<<EOF
pf d? x (bar)moo
   x : 0x00000000 = 0x00000000
 moo : 
                struct<bar>
   a : 0x00000004 = 0x00000000
   b : 0x00000008 = 0x00000000
EOF
RUN

NAME=Array of struct with ts
FILE=-
CMDS=<<EOF
"td struct bar { int a; int b; };"
"td struct foo { int x; struct bar moo[2]; };"
ts foo
.ts foo
EOF
EXPECT=<<EOF
pf d[2]? x (bar)moo
   x : 0x00000000 = 0x00000000
 moo : 
[
                struct<bar>
   a : 0x00000004 = 0x00000000
   b : 0x00000008 = 0x00000000

                struct<bar>
   a : 0x0000000c = 0x00000000
   b : 0x00000010 = 0x00000000
]
EOF
RUN

NAME=te <enum>
FILE=-
CMDS=<<EOF
"td enum Foo {COW=1,BAR=2};"
te
te Foo
EOF
EXPECT=<<EOF
Foo
COW = 0x1
BAR = 0x2
EOF
RUN

NAME=te <enum> <value>
FILE=-
CMDS=<<EOF
"td enum Foo {COW=1,BAR=2};"
te Foo 1
EOF
EXPECT=<<EOF
COW
EOF
RUN

NAME=teb <enum> <name>
FILE=-
CMDS=<<EOF
"td enum Foo {COW=1,BAR=2};"
teb Foo COW
EOF
EXPECT=<<EOF
0x1
EOF
RUN

NAME=afsafv
FILE=bins/mach0/ls-osx-x86_64
CMDS=<<EOF
aa
s main
afs
afs*
?e original
afv~arg
?e deleted
afv-*
afv~arg
?e recovered from signature
.afs*
afv~arg
EOF
EXPECT=<<EOF
int main (int argc, char **argv);
tn main
afc amd64
afvr rdi argc int
afvr rsi argv char **

original
arg int argc @ rdi
arg char ** argv @ rsi
deleted
recovered from signature
arg int argc @ rdi
arg char ** argv @ rsi
EOF
RUN

NAME=truncated tp
FILE=-
CMDS=<<EOF
"td struct foobar{uint32_t a; uint32_t b; uint32_t c; uint32_t d;}"
b 64
woe 1
tp foobar
b 4
tp foobar
EOF
EXPECT=<<EOF
 a : 0x00000000 = 0x03020100
 b : 0x00000004 = 0x07060504
 c : 0x00000008 = 0x0b0a0908
 d : 0x0000000c = 0x0f0e0d0c
 a : 0x00000000 = 0x03020100
 b : 0x00000004 = 0x07060504
 c : 0x00000008 = 0x0b0a0908
 d : 0x0000000c = 0x0f0e0d0c
EOF
RUN

NAME=tp with varname
FILE=bins/elf/struct_sample
CMDS=<<EOF
"td struct Books {char  title[50];char  author[50]; char  subject[100];};"
aa
s main
aei
aeim
aecu 0x000006d5
?e
tp Books var_e0h
EOF
EXPECT=<<EOF

   title : 0x00177f18 = "Radare2"
  author : 0x00177f4a = "pancake"
 subject : 0x00177f7c = "Reversing"
EOF
RUN

NAME=tpx test
FILE=-
CMDS=<<EOF
"td struct foo {char* a; int b;}"
tpx foo 41414141441414141414420010000000
EOF
EXPECT=<<EOF
 a : 0x00000000 = "AAAAD\x14\x14\x14\x14\x14B"
 b : 0x0000000c = 0x00000010
EOF
RUN

NAME=aht and arm
FILE=-
CMDS=<<EOF
e asm.arch = arm
e asm.bits = 32
wx 082090e5040081e5
"td struct foo {int a; int b; int c;};"
aht foo.c @ 0x00000000
aht foo.b @ 0x00000004
?e
pd 2
EOF
EXPECT=<<EOF

            0x00000000      082090e5       ldr r2, [r0, foo.c]
            0x00000004      040081e5       str r0, [r1, foo.b]
EOF
RUN

NAME=aht and mips
FILE=-
CMDS=<<EOF
e asm.arch=mips
wx 08007fac040053800800538c
"td struct foo {int a; int b; int c;};"
aht foo.c @ 0x00000000
aht foo.c @ 0x00000008
aht foo.b @ 0x00000004
?e
pd 3
EOF
EXPECT=<<EOF

            0x00000000      08007fac       sw ra, foo.c(v1)
            0x00000004      04005380       lb s3, foo.b(v0)
            0x00000008      0800538c       lw s3, foo.c(v0)
EOF
RUN

NAME=struct offset for dst operand with aht
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=32
"td struct foo {int a; int b ; int c;}"
wx 8b40048951048d500883780800
?e
aht foo.b @ 0x00000000
aht foo.b @ 0x00000003
aht foo.c @ 0x00000006
aht foo.c @ 0x00000009
pd 4
EOF
EXPECT=<<EOF

            0x00000000      8b4004         mov eax, dword [eax + foo.b]
            0x00000003      895104         mov dword [ecx + foo.b], edx
            0x00000006      8d5008         lea edx, [eax + foo.c]
            0x00000009      83780800       cmp dword [eax + foo.c], 0
EOF
RUN

NAME=struct offset propagate via tl
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e asm.comments = false
"td struct bar {int a ; int b; int c;}"
wx 48C7C058190000488B5004488B4808483B500448BBEFBEADDE00000000488958089090C3
af
tl bar = 0x1958
?e
pdf~bar.
EOF
EXPECT=<<EOF

|           0x00000007      488b5004       mov rdx, qword [rax + bar.b]
|           0x0000000b      488b4808       mov rcx, qword [rax + bar.c]
|           0x0000000f      483b5004       cmp rdx, qword [rax + bar.b]
|           0x0000001d      48895808       mov qword [rax + bar.c], rbx
EOF
RUN

NAME=aat with single struct
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e asm.comments = false
"td struct bar {int a ; int b; int c;}"
wx 48C7C058190000488B5004488B4808483B500448BBEFBEADDE00000000488958089090C3
tl bar = 0x1958
af
aat @ fcn.00000000
?e
pdf~bar.
EOF
EXPECT=<<EOF

|           0x00000007      488b5004       mov rdx, qword [rax + bar.b]
|           0x0000000b      488b4808       mov rcx, qword [rax + bar.c]
|           0x0000000f      483b5004       cmp rdx, qword [rax + bar.b]
|           0x0000001d      48895808       mov qword [rax + bar.c], rbx
EOF
RUN

NAME=aat with multiple struct
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e asm.comments = false
e asm.flags = false
"td struct bar {int x; int y; int z;};"
"td struct foo {int a; int b; int c;};"
wx 48C7C000010000488B5008488B480448C7C000020000488B5008488B48049090C3
tl bar = 0x200
tl foo = 0x100
af
aat
pdf
EOF
EXPECT=<<EOF
/ 33: fcn.00000000 ();
|           0x00000000      48c7c00001..   mov rax, 0x100
|           0x00000007      488b5008       mov rdx, qword [rax + foo.c]
|           0x0000000b      488b4804       mov rcx, qword [rax + foo.b]
|           0x0000000f      48c7c00002..   mov rax, 0x200
|           0x00000016      488b5008       mov rdx, qword [rax + bar.z]
|           0x0000001a      488b4804       mov rcx, qword [rax + bar.y]
|           0x0000001e      90             nop
|           0x0000001f      90             nop
\           0x00000020      c3             ret
EOF
RUN

NAME=Comments and var in struct offset propagation
FILE=bins/elf/struct_sample
CMDS=<<EOF
aa
s main
"td struct Books {char  title[50];char  author[50]; char  subject[100];};"
tl Books = 0x00177f18
?e
pdf~Books
EOF
EXPECT=<<EOF

|           ; var struct Books @ rbp-0xe0
|           0x00000684      488d8520ff..   lea rax, [Books]
|           0x00000695      488910         mov qword [rax], rdx        ; Books.title
|           0x00000698      488d8520ff..   lea rax, [Books]
|           0x000006ad      488908         mov qword [rax], rcx        ; Books.author
|           0x000006b0      488d8520ff..   lea rax, [Books]
|           0x000006c5      488930         mov qword [rax], rsi        ; Books.subject
|           0x000006d5      b800000000     mov eax, 0                  ; Books.subject
EOF
RUN

NAME=tl with ahr (return value hint)
FILE=bins/elf/struct_2
CMDS=<<EOF
aa
"td struct Test { int a; int  b; char *c;};"
s main
ahr 0x00000597 @ 0x00000592
tl Test = 0x00002020
s 0x000005a8
?e
pd 3
EOF
EXPECT=<<EOF

|           0x000005a8      c70206000000   mov dword [edx], 6          ; Test.a
|           0x000005ae      8b55f4         mov edx, dword [Test]       ; Test.a
|           0x000005b1      c742040700..   mov dword [edx + Test.b], 7
EOF
RUN

NAME=Basic union test
FILE=bins/elf/union_sample
CMDS=<<EOF
aa
"td union Books {char  title[50];char  author[50]; char  subject[100];};"
tu
tu Books
s main
tl Books = 0x00177f88
afv~Books
s 0x000006d2
pd 1
EOF
EXPECT=<<EOF
Books
pf [50]z[50]z[100]z title author subject
var union Books @ rbp-0x70
|           0x000006d2      488d4590       lea rax, [Books]
EOF
RUN

NAME=ts function pointer test
FILE=-
CMDS=<<EOF
e asm.bits=64
ws hello @ 0xc
"td struct foo {int x; int (*fp)(int a , int b ); char *b;};"
ts foo
.ts foo
EOF
EXPECT=<<EOF
pf dpz x fp b
  x : 0x00000000 = 0x00000000
 fp : 0x00000004 = (qword)0x0000000000000000
  b : 0x0000000c = "\x05hello"
EOF
RUN

NAME=ts general pointers test
FILE=-
CMDS=<<EOF
"td struct normal {int a;char b;};"
"td struct pointer {char *y;struct normal *obj;};"
ts pointer
EOF
EXPECT=<<EOF
pf zp y obj
EOF
RUN

NAME=tsc test
FILE=-
CMDS=<<EOF
"td struct three_elements{int x; char y; float z;}"
tsc three_elements
EOF
EXPECT=<<EOF
struct three_elements {
  int32_t x;
  char y;
  float z;
};
EOF
RUN

NAME=tsc with array
FILE=-
CMDS=<<EOF
"td struct with_array{int x; char y[50]; float z;}"
tsc with_array
EOF
EXPECT=<<EOF
struct with_array {
  int32_t x;
  char y[50];
  float z;
};
EOF
RUN

NAME=tec test
FILE=-
CMDS=<<EOF
"td enum Foo {COW=1,BAR=2};"
tec Foo
EOF
EXPECT=<<EOF
enum Foo {
	COW = 1,
	BAR = 2
};
EOF
RUN

NAME=tuc test
FILE=-
CMDS=<<EOF
"td union x{int x; int y; int z;}"
tuc x
EOF
EXPECT=<<EOF
union x {
  int32_t x;
  int32_t y;
  int32_t z;
};
EOF
RUN

NAME=ttc test
FILE=-
CMDS=<<EOF
"td typedef char FILE_NAME;"
ttc FILE_NAME
EOF
EXPECT=<<EOF
typedef char FILE_NAME;
EOF
RUN

NAME=tcd test
FILE=-
CMDS=<<EOF
t-*
"td typedef char FILE_NAME;"
"td union x{int x; int y; int z;}"
"td enum Foo {COW=1,BAR=2};"
"td struct three_elements{int x; char y; float z;}"
tcd
EOF
EXPECT=<<EOF
union x {int32_t x; int32_t y; int32_t z;};
struct three_elements {int32_t x; char y; float z;};
typedef char FILE_NAME;
enum Foo {COW = 1, BAR = 2};
EOF
RUN

NAME=typedef struct
FILE=-
CMDS=<<EOF
to bins/headers/12272.h
ts A
ts B
ts O  # Broken but shouldn't hang
?e ----
tk~typedef.A=,typedef.B=,typedef.O=,struct.A,struct.B,struct.O
?e
ts~A,B,O
EOF
EXPECT=<<EOF
pf dF num num2
pf c ch
----
struct.A=num
struct.A.num=float,0,0
struct.A.num.meta=9
struct.O=ptr
struct.O.ptr=char *,0,0
struct.O.ptr.meta=4
typedef.A=struct
typedef.B=struct
typedef.O=struct O

A
B
O
EOF
RUN

NAME=typedef struct double header
FILE=-
CMDS=<<EOF
to bins/headers/hdr1.h
to bins/headers/hdr2.h
ts A
ts B
?e
to bins/headers/hdr1.h
to bins/headers/hdr2.h
tk~^struct.0,struct.1,struct.2,struct.3
?e
ts~^0,1,2,3,A,B
EOF
EXPECT=<<EOF
pf f num
pf c ch


A
B
EOF
RUN

NAME=Backward param type propgation
FILE=bins/elf/back1
CMDS=<<EOF
aa
s main
aaft
afv
EOF
EXPECT=<<EOF
var char * src @ rbp-0x8
var char * dest @ rbp-0x10
var size_t size @ rbp-0x14
EOF
RUN

NAME=Forward param type propgation
FILE=bins/elf/forward1
CMDS=<<EOF
aa
s main
aaft
afv
EOF
EXPECT=<<EOF
var char * src @ rbp-0x8
var char * ptr @ rbp-0x10
var size_t size @ rbp-0x14
EOF
RUN

NAME=Propgation via value
FILE=bins/elf/follow_ptr
CMDS=<<EOF
aa
s main
aaft
afv
EOF
EXPECT=<<EOF
var char * var_8h @ rbp-0x8
var char * s @ rbp-0x10
var char * var_18h @ rbp-0x18
var size_t var_1ch @ rbp-0x1c
EOF
RUN

NAME=General type propgation
FILE=bins/elf/hello_world
CMDS=<<EOF
aa
s main
aaft
afv
EOF
EXPECT=<<EOF
var char * dest @ rbp-0x8
var char * s2 @ rbp-0x10
var char * src @ rbp-0x18
var size_t size @ rbp-0x1c
var size_t var_20h @ rbp-0x20
EOF
RUN

NAME=32-bit bin type propgation
FILE=bins/elf/hello_world32
CMDS=<<EOF
aa
s main
aaft
afv
EOF
EXPECT=<<EOF
arg char ** argv @ esp+0x44
var int32_t var_8h @ ebp-0x8
var char * dest @ ebp-0xc
var size_t size @ ebp-0x10
var size_t var_14h @ ebp-0x14
var char * s2 @ ebp-0x18
var char * src @ ebp-0x1c
EOF
RUN

NAME=Register based var
FILE=bins/elf/arg
CMDS=<<EOF
aa
s sym.funcarg
afvr
EOF
EXPECT=<<EOF
arg int64_t arg1 @ rdi
arg int64_t arg2 @ rsi
arg int64_t arg3 @ rdx
arg int64_t arg4 @ rcx
EOF
RUN

NAME=Type propgation for reg based arg
FILE=bins/elf/arg
CMDS=<<EOF
aa
aaft
s sym.funcarg
afvr
EOF
EXPECT=<<EOF
arg char * arg1 @ rdi
arg char * arg2 @ rsi
arg int64_t arg3 @ rdx
arg size_t arg4 @ rcx
EOF
RUN

NAME=Caller to callee propgation (64 bits)
FILE=bins/elf/arg_down_prop
CMDS=<<EOF
e asm.lines = false
e asm.xrefs = false
aa
aaft
s sym.funcarg
pd 1
EOF
EXPECT=<<EOF
154: sym.funcarg (char *arg1, uint32_t arg2);
; arg char *arg1 @ rdi
; arg uint32_t arg2 @ rsi
; var char *var_8h @ rbp-0x8
; var uint32_t var_ch @ rbp-0xc
0x0000068a      55             push rbp
EOF
RUN

NAME=Caller to caller propgation (32 bits)
FILE=bins/elf/arg_down_32
CMDS=<<EOF
e asm.lines = false
e asm.xrefs = false
aa
aaft
s sym.funcarg
pd 1
EOF
EXPECT=<<EOF
147: sym.funcarg (char *arg_8h, uint32_t arg_ch);
; arg char *arg_8h @ ebp+0x8
; arg uint32_t arg_ch @ ebp+0xc
; var int32_t var_4h @ ebp-0x4
0x0000054d      55             push ebp
EOF
RUN

NAME=Type Propagation
FILE=bins/pe/debugme.exe
BROKEN=1
CMDS=<<EOF
aaaa
pd 1 @ 0x00401792~?[n
pd 1 @ 0x00401796~?[c
pd 1 @ 0x0040179e~?[s
pd 1 @ 0x004017b1~?[n
pd 1 @ 0x004017b5~?[c
pd 1 @ 0x004017bd~?[s
pd 1 @ 0x0040186a~?[s2
pd 1 @ 0x0040186e~?[s1
pd 1 @ 0x0040152f~?[dwInitParam
pd 1 @ 0x00401537~?[lpDialogFunc
pd 1 @ 0x0040153f~?[hWndParent
pd 1 @ 0x00401547~?[lpTemplateName
pd 1 @ 0x00401554~?[hInstance
EOF
EXPECT=<<EOF
1
1
1
1
1
1
1
1
1
1
1
1
1
EOF
RUN

NAME=Double pointer test
FILE=bins/elf/double_ptr
CMDS=<<EOF
aa
aaft
s main
afv~ptr
EOF
EXPECT=<<EOF
var char ** ptr @ rbp-0x18
EOF
RUN

NAME=Signed and unsigned test
FILE=bins/elf/signed_test
CMDS=<<EOF
aa
aaft
s main
afv~sign
afv~uint
EOF
EXPECT=<<EOF
var signed int64_t var_30h @ rbp-0x30
var signed int64_t var_34h @ rbp-0x34
var uint32_t var_28h @ rbp-0x28
EOF
RUN

NAME=flagspace analysis
FILE=bins/elf/flagspace
CMDS=<<EOF
aa
aaft
s main
afv
EOF
EXPECT=<<EOF
var int64_t canary @ rbp-0x8
var char * var_10h @ rbp-0x10
var char * var_18h @ rbp-0x18
var char * s @ rbp-0x20
var FILE * stream @ rbp-0x28
var uint32_t var_2ch @ rbp-0x2c
var signed int64_t var_30h @ rbp-0x30
var int64_t var_34h @ rbp-0x34
EOF
RUN

NAME=bashbot test (x86_64)
FILE=bins/elf/bashbot.x86_64.O0.elf
CMDS=<<EOF
aa
aaft
s main
afv
s sym.processCmd
afv
EOF
EXPECT=<<EOF
arg int argc @ rdi
arg char ** argv @ rsi
var int64_t var_18h @ rbp-0x18
var char * s1 @ rbp-0x1020
var void * var_1420h @ rbp-0x1420
var char * dest @ rbp-0x1470
var void * var_1478h @ rbp-0x1478
var char * var_1480h @ rbp-0x1480
var char * v2 @ rbp-0x1488
var char * src @ rbp-0x1490
var char * var_1498h @ rbp-0x1498
var char * s @ rbp-0x14a0
var char * var_14a8h @ rbp-0x14a8
var int64_t var_14ach @ rbp-0x14ac
var uint32_t var_14b0h @ rbp-0x14b0
var uint32_t var_14b4h @ rbp-0x14b4
var pid_t pid @ rbp-0x14b8
var int64_t var_14bch @ rbp-0x14bc
var signed int64_t var_14c0h @ rbp-0x14c0
var int64_t var_14c4h @ rbp-0x14c4
var int64_t options @ rbp-0x14c8
var int64_t wstatus @ rbp-0x14cc
var int64_t var_14d4h @ rbp-0x14d4
var char ** var_14e0h @ rbp-0x14e0
arg signed int arg1 @ rdi
arg char * arg2 @ rsi
var int64_t var_8h @ rbp-0x8
var int64_t var_18h @ rbp-0x18
var char * var_20h @ rbp-0x20
var char * var_28h @ rbp-0x28
var char * s @ rbp-0x30
var char * s1 @ rbp-0x38
var uint32_t var_40h @ rbp-0x40
var char * var_48h @ rbp-0x48
var char * var_50h @ rbp-0x50
var char * var_58h @ rbp-0x58
var char * var_60h @ rbp-0x60
var int64_t var_64h @ rbp-0x64
var int64_t var_68h @ rbp-0x68
var int64_t var_6ch @ rbp-0x6c
var int64_t var_70h @ rbp-0x70
var int64_t var_74h @ rbp-0x74
var int64_t var_78h @ rbp-0x78
var int64_t var_7ch @ rbp-0x7c
var int64_t var_80h @ rbp-0x80
var int64_t var_84h @ rbp-0x84
var int64_t var_88h @ rbp-0x88
var int64_t var_8ch @ rbp-0x8c
var int64_t var_90h @ rbp-0x90
var int64_t var_94h @ rbp-0x94
var int64_t var_98h @ rbp-0x98
var uint32_t var_9ch @ rbp-0x9c
var signed int64_t var_a0h @ rbp-0xa0
var signed int var_a4h @ rbp-0xa4
var char * str @ rbp-0xb0
EOF
RUN

NAME=bashbot test (arm 32-bits)
FILE=bins/elf/bashbot.arm.gcc.O0.elf
CMDS=<<EOF
e anal.vars.stackname=true
s main
af
aaft
afv
EOF
EXPECT=<<EOF
arg int argc @ r0
arg char ** argv @ r1
var int32_t var_1460h @ sp+0x0
var char * option @ fp-0xc
var int32_t var_14h @ fp-0x10
var int32_t var_18h @ fp-0x14
var char * var_1ch @ fp-0x18
var char * s @ fp-0x1c
var char * var_24h @ fp-0x20
var int32_t var_28h @ fp-0x24
var char * src @ fp-0x28
var int32_t var_30h @ fp-0x2c
var char * v2 @ fp-0x30
var pid_t pid @ fp-0x34
var int32_t var_3ch @ fp-0x38
var int32_t var_40h @ fp-0x3c
var int32_t var_44h @ fp-0x40
var char * var_48h @ fp-0x44
var int32_t var_4ch @ fp-0x48
var int32_t wstatus @ fp-0x4c
var char * s1 @ fp-0x1040
var void * var_1444h @ fp-0x1440
EOF
RUN

NAME=format string parse
FILE=bins/elf/format
CMDS=<<EOF
aa
aaft
s main
afv
EOF
EXPECT=<<EOF
var char * var_8h @ rbp-0x8
var long int var_10h @ rbp-0x10
var char * var_18h @ rbp-0x18
var int64_t var_1ch @ rbp-0x1c
var uint32_t var_20h @ rbp-0x20
var signed int64_t var_24h @ rbp-0x24
var int64_t var_25h @ rbp-0x25
EOF
RUN

NAME=local to register var type propgation
FILE=bins/elf/l2rbin
CMDS=<<EOF
aa
aaft
s main
afv
EOF
EXPECT=<<EOF
arg int argc @ rdi
arg char ** argv @ rsi
arg char ** envp @ rdx
var int64_t var_4h @ rbp-0x4
var void * var_10h @ rbp-0x10
var int64_t var_14h @ rbp-0x14
var char ** var_20h @ rbp-0x20
var char ** var_28h @ rbp-0x28
EOF
RUN

NAME=constrained type
FILE=bins/elf/constr_type
CMDS=<<EOF
e anal.types.constraint = true
aaa
s sym.single_cond
pd 1~4h
s sym.range_small
pd 1~14h
s sym.range_high
pd 1~4h
s sym.range_or
pd 1~4h
EOF
EXPECT=<<EOF
|           ; var signed int64_t var_4h  { > 0xa } @ rbp-0x4
|           ; var signed int64_t var_14h  { > 0x0 && <= 0x9 } @ rbp-0x14
|           ; var signed int64_t var_4h  { > 0x64 && <= 0xc7 } @ rbp-0x4
|           ; var signed int64_t var_4h  { > 0xff && <= 0x12b || > 0x14 && <= 0x31 || > 0x6f && <= 0xdd } @ rbp-0x4
EOF
RUN

NAME=mov str
FILE=bins/elf/movstr
CMDS=<<EOF
e anal.vars.stackname=true
aaa
s main
afv~var_28h
EOF
EXPECT=<<EOF
var char * var_28h @ esp+0x4
EOF
RUN

NAME=ret type pointer
FILE=bins/elf/tie-test
CMDS=<<EOF
aaa
s sym.foo
afv~var_20h
EOF
EXPECT=<<EOF
var size_t * var_20h @ rbp-0x20
EOF
RUN

NAME=types size
CMDS=<<EOF
"td struct s1 { int a; int size; int b; };"
tk~struct.s1
EOF
EXPECT=<<EOF
struct.s1=a,size,b
struct.s1.a=int32_t,0,0
struct.s1.a.meta=0
struct.s1.b=int32_t,8,0
struct.s1.b.meta=0
struct.s1.size=int32_t,4,0
struct.s1.size.meta=0
EOF
RUN

NAME=types afs [before]
FILE=bins/elf/hello_world
CMDS=<<EOF
s main
af
tk~func.main
EOF
EXPECT=<<EOF
func.main.arg.0=int,argc
func.main.arg.1=char **,argv
func.main.arg.2=char **,envp
func.main.args=3
func.main.ret=int
EOF
RUN

NAME=types afs [after]
FILE=bins/elf/hello_world
CMDS=<<EOF
s main
af
"afs int main(int argc);"
tk~func.main
EOF
EXPECT=<<EOF
func.main.arg.0=int32_t,argc
func.main.args=1
func.main.cc=cdecl
func.main.ret=int32_t
EOF
RUN

NAME=afs without type
FILE=bins/elf/analysis/pid_stripped
CMDS=<<EOF
e anal.vars.stackname=true
s 0x4e2420
af
afs
"afs no_type(int a, char **b);"
afs
"afs char type(int a, char **b);"
afs
EOF
EXPECT=<<EOF
void fcn.004e2420 (int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4, int64_t arg5, int64_t arg6, int64_t arg_8h);
int32_t no_type (int32_t a, char **b);
char type (int32_t a, char **b);
EOF
RUN

NAME=afs fcnname with dots
FILE=bins/elf/hello_world
CMDS=<<EOF
af
afs
"afs foo.bar();"
afs
"afs char foo.bar(int a, ...);"
afs
EOF
EXPECT=<<EOF
void entry0 (int64_t arg3);
int32_t foo.bar ();
char foo.bar (int32_t a);
EOF
RUN

NAME=afs sym.imp.*
FILE=bins/elf/hello_world
CMDS=<<EOF
s sym.imp.strlen
af
afs
EOF
EXPECT=<<EOF
size_t strlen (const char *s);
EOF
RUN

NAME=td crash
FILE=-
CMDS=<<EOF
"td struct;"
"td struct crash __attribute__((packed)) { };"
EOF
EXPECT=<<EOF
EOF
RUN

NAME=tn common
FILE=bins/pe/pe.exe
CMDS=<<EOF
tna 8
tnn 8
tn
tn- 0x8
tn- 8
tn
tn-*
tn
EOF
EXPECT=<<EOF
err
errc
RtlRaiseException
FreeLibraryAndExitThread
ExitProcess
FatalExit
RaiseException
errx
ExitThread
8
0x8
err
errc
RtlRaiseException
FreeLibraryAndExitThread
ExitProcess
FatalExit
RaiseException
errx
ExitThread
EOF
RUN

NAME=td union
FILE=-
CMDS=<<EOF
"td union foo {int a;char b;}"
tu*~foo
ts*~foo
t*~foo
t foo
tu* foo
EOF
EXPECT=<<EOF
pf.foo dc a b
"tk foo=union"
"tk union.foo=a,b"
"tk union.foo.a=int32_t,0,0"
"tk union.foo.a.meta=0"
"tk union.foo.b=char,0,0"
"tk union.foo.b.meta=2"
pf dc a b
pf.foo dc a b
EOF
RUN

NAME=td uint64_t
FILE=-
CMDS=<<EOF
wx 0xa00f
wx 0x401f @ 0x4
wx 0800000000000080 @ 0x8
"td struct foo {int a; int b; uint64_t c;};"
tl foo @ 0x0
pd 1
EOF
EXPECT=<<EOF
(foo)
 a : 0x00000000 = 0x00000fa0
 b : 0x00000004 = 0x00001f40
 c : 0x00000008 = (qword)0x8000000000000008
EOF
RUN

NAME=td empty struct
FILE=-
CMDS=<<EOF
wx 0xa00f
wx 0x401f @ 0x4
wx 0800000000000080 @ 0x8
"td struct foo {};"
tl foo @ 0x0
pd 1
EOF
EXPECT=<<EOF
(foo)
EOF
RUN

NAME=type xrefs
FILE=bins/elf/ls.odd
CMDS=<<EOF
aaaa
txf main
?e =
txf fcn.00011b90
?e =
txt size_t
?e =
txt size_t *
EOF
EXPECT=<<EOF
int
char **
int64_t
char *
=
uint32_t
int64_t
char *
size_t *
size_t
void *
wint_t
=
fcn.0000f770
fcn.00011b90
fcn.00010010
fcn.0000e780
fcn.0000c0f0
=
fcn.00011b90
fcn.00014d50
EOF
RUN

NAME=aht aligned
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
"td struct foo {char gap;int bar __attribute__((__aligned__(4)));};"
"td struct foo2 {char gap[1];int bar __attribute__((__aligned__(4)));};"
"td struct foo3 {char gap[3];int bar __attribute__((__aligned__(4)));};"
"td struct foo4 {char gap[4];int bar;};"
"td struct foo5 {int gap;int bar;};"
ahts 4 ~foo
?e =
wx c7400400000000
aht foo.bar
pd 1
EOF
EXPECT=<<EOF
foo.bar
foo2.bar
foo3.bar
foo4.bar
foo5.bar
=
            0x00000000      c740040000..   mov dword [rax + foo.bar], 0
EOF
RUN

NAME=ahts nested
FILE=-
CMDS=<<EOF
"td struct foo {int bar;int cow;};"
"td struct spam {int ham;struct foo _foo;int eggs;};"
ahts 8 ~spam
EOF
EXPECT=<<EOF
spam._foo.cow
EOF
RUN

NAME=aaft io.va side effect
FILE=-
ARGS=-eio.va=0 -a x86 -b 64
CMDS=<<EOF
af
aaft
e io.va
EOF
EXPECT=<<EOF
false
EOF
RUN

NAME=types afs [before] 2
FILE=bins/elf/hello_world
CMDS=<<EOF
aaa
s main
afs
afsj~{}
s sym.imp.strcpy
afs
afsj~{}
EOF
EXPECT=<<EOF
int main (int argc, char **argv, char **envp);
{
  "name": "main",
  "noreturn": false,
  "ret": "int",
  "cc": "amd64",
  "argc": 3,
  "args": [
    {
      "name": "argc",
      "type": "int",
      "cc": "rdi"
    },
    {
      "name": "argv",
      "type": "char **",
      "cc": "rsi"
    },
    {
      "name": "envp",
      "type": "char **",
      "cc": "rdx"
    }
  ]
}
char * strcpy (char *dest, const char *src);
{
  "name": "sym.imp.strcpy",
  "noreturn": false,
  "ret": "char *",
  "cc": "amd64",
  "argc": 2,
  "args": [
    {
      "name": "dest",
      "type": "char *",
      "cc": "rdi"
    },
    {
      "name": "src",
      "type": "const char *",
      "cc": "rsi"
    }
  ]
}
EOF
RUN

NAME=typedef stuff
FILE=--
CMDS=<<EOF
"td typedef int Number";
tt
tt Number
tk~Number
t Number
EOF
EXPECT=<<EOF
Number
int32_t
Number=typedef
typedef.Number=int32_t
pf d
EOF
RUN
