# merged: af import; afll
NAME=afcf ls
FILE=bins/mach0/ls-osx-x86_64
CMDS=<<EOF
af@main
afcf main @ 0
afcf @ main
afcfj @ main
?e --
s sym.imp.write
af
afi~realsz
?v $FS
?e --
aa ; afll~?main
EOF
EXPECT=<<EOF
int main (int argc, char **argv, char **envp);
int main (int argc, char **argv, char **envp);
[{"name":"main","return":"int","args":[{"name":"argc","type":"int"},{"name":"argv","type":"char **"},{"name":"envp","type":"char **"}],"count":3}]
--
realsz: 6
0x6
--
1
EOF
RUN

NAME=af localflag
FILE=bins/mach0/mac-ls2
CMDS=<<EOF
af
f.foobar=0x100001216
pd 20~foo
EOF
EXPECT=<<EOF
|       ,=< 0x10000120f      7f05           jg .foobar                 ; main.foobar
|       |    .foobar:
EOF
RUN

NAME=af switch test
FILE=bins/mach0/mac-ls2
CMDS=<<EOF
af
axf@0x100001308
EOF
EXPECT=<<EOF
CODE 0x1000012dc case.0x100001308.50
CODE 0x10000130a case.0x100001308.49
CODE 0x100001321 case.0x100001308.114
CODE 0x10000132a case.0x100001308.120
CODE 0x100001347 case.0x100001308.118
CODE 0x100001353 case.0x100001308.99
CODE 0x100001370 case.0x100001308.102
CODE 0x100001392 case.0x100001308.97
CODE 0x100001396 case.0x100001308.65
CODE 0x1000013a2 case.0x100001308.84
CODE 0x1000013b1 case.0x100001308.107
CODE 0x1000013bd case.0x100001308.115
CODE 0x1000013cc case.0x100001308.76
CODE 0x1000013fb case.0x100001308.104
CODE 0x10000140a case.0x100001308.80
CODE 0x10000141a case.0x100001308.110
CODE 0x10000143f case.0x100001308.108
CODE 0x10000144b case.0x100001308.103
CODE 0x100001473 case.0x100001308.83
CODE 0x10000147f case.0x100001308.100
CODE 0x100001492 case.0x100001308.111
CODE 0x1000014d0 case.0x100001308.79
CODE 0x1000014df case.0x100001308.113
CODE 0x1000014f0 case.0x100001308.64
CODE 0x1000014ff case.0x100001308.67
CODE 0x100001519 case.0x100001308.82
CODE 0x100001525 case.0x100001308.70
CODE 0x10000153e case.0x100001308.66
CODE 0x10000155b case.0x100001308.105
CODE 0x10000156a case.0x100001308.119
CODE 0x100001583 case.0x100001308.85
CODE 0x1000015a0 case.0x100001308.87
CODE 0x1000015ac case.0x100001308.71
CODE 0x1000015c9 case.0x100001308.72
CODE 0x1000015f7 case.0x100001308.112
CODE 0x10000160d case.0x100001308.98
CODE 0x10000162a case.0x100001308.116
CODE 0x100001636 case.0x100001308.101
CODE 0x100001645 case.0x100001308.109
CODE 0x100001665 case.0x100001308.117
CODE 0x100001682 case.default.0x100001308
EOF
RUN

NAME=missing bb fix
FILE=bins/elf/before-after-main
CMDS=<<EOF
e asm.bytes=false
e asm.comments=false
s sym.register_tm_clones
af
pdf
EOF
EXPECT=<<EOF
/ 53: sym.register_tm_clones ();
|           0x08048410      mov eax, obj.completed.6891
|           0x08048415      sub eax, obj.completed.6891
|           0x0804841a      sar eax, 2
|           0x0804841d      mov edx, eax
|           0x0804841f      shr edx, 0x1f
|           0x08048422      add eax, edx
|           0x08048424      sar eax, 1
|       ,=< 0x08048426      je 0x8048448
|       |   0x08048428      mov edx, 0
|       |   0x0804842d      test edx, edx
|      ,==< 0x0804842f      je 0x8048448
|      ||   0x08048431      push ebp
|      ||   0x08048432      mov ebp, esp
|      ||   0x08048434      sub esp, 0x10
|      ||   0x08048437      push eax
|      ||   0x08048438      push obj.completed.6891
|      ||   0x0804843d      call edx
|      ||   0x0804843f      add esp, 0x10
|      ||   0x08048442      leave
|      ||   0x08048443      ret
..
\      ``-> 0x08048448      ret
EOF
RUN

NAME=afb+
FILE=bins/pe/a.exe
CMDS=<<EOF
s 0x004017c0
af+ 0x004017c0 fcn2.0x004017c0
afb+ 0x4017c0 0x4017c0 13 0x4017dd 0x4017cd
afi~size
afb
?e
pdf
?e
af-
af+ 0x004017c0 fcn2.0x004017c0
afb+ 0x4017c0 0x4017c0 6 0x4017dd 0x4017cd
afi~size
afb
?e
pdf
?e
afb+ 0x4017c0 0x4017c0 11 0x4017dd 0x4017cd
afi~size
afb
?e
pdf
EOF
EXPECT=<<EOF
size: 13
0x004017c0 0x004017cd 00:0000 13 j 0x004017dd f 0x004017cd

/ 13: fcn2.0x004017c0 ();
|           0x004017c0      51             push ecx
|           0x004017c1      89e1           mov ecx, esp
|           0x004017c3      83c108         add ecx, 8
|           0x004017c6      3d00100000     cmp eax, 0x1000
\       ,=< 0x004017cb      7210           jb 0x4017dd

size: 6
0x004017c0 0x004017c6 00:0000 6 j 0x004017dd f 0x004017cd

/ 6: fcn2.0x004017c0 ();
|           0x004017c0      51             push ecx
|           0x004017c1      89e1           mov ecx, esp
\           0x004017c3      83c108         add ecx, 8

size: 11
0x004017c0 0x004017cb 00:0000 11 j 0x004017dd f 0x004017cd

/ 11: fcn2.0x004017c0 ();
|           0x004017c0      51             push ecx
|           0x004017c1      89e1           mov ecx, esp
|           0x004017c3      83c108         add ecx, 8
\           0x004017c6      3d00100000     cmp eax, 0x1000
EOF
EXPECT_ERR=
RUN

NAME=afbi lists every switch case and leaves them in the analysis
FILE=malloc://64
ARGS=-a x86 -b 64
CMDS=<<EOF
af+ 0 foo
afb+ 0 0 16
afbe 0 0x20
afbe 0 0x20
afbe 0 0x30
afbi~case
afbi~case
EOF
EXPECT=<<EOF
cases: 3
case.0: 0x00000020
case.0: 0x00000020
case.0: 0x00000030
cases: 3
case.0: 0x00000020
case.0: 0x00000020
case.0: 0x00000030
EOF
RUN

NAME=afb dedupes the printed successors without dropping the cases
FILE=malloc://64
ARGS=-a x86 -b 64
CMDS=<<EOF
af+ 0 foo
afb+ 0 0 16
afbe 0 0x20
afbe 0 0x20
afbe 0 0x30
afb
afbi~case
EOF
EXPECT=<<EOF
0x00000000 0x00000010 00:0000 16 s 0x00000020 s 0x00000030
cases: 3
case.0: 0x00000020
case.0: 0x00000020
case.0: 0x00000030
EOF
RUN

NAME=Adding basic blocks with with wrong size (afb+)
FILE=bins/pe/a.exe
CMDS=<<EOF
s 0x004017c0
af+ 0x004017c0 fcn2.0x004017c0
afb+ 0x4017c0 0x4017c0 9 0x4017dd 0x4017cd
afi~size
afb
?e
pdf
?e
pdr
?e
afb+ 0x4017c0 0x4017c0 12 0x4017dd 0x4017cd
afi~size
afb
?e
pdf
?e
pdr
EOF
EXPECT=<<EOF
size: 9
0x004017c0 0x004017c9 00:0000 9 j 0x004017dd f 0x004017cd

/ 9: fcn2.0x004017c0 ();
|           0x004017c0      51             push ecx
|           0x004017c1      89e1           mov ecx, esp
|           0x004017c3      83c108         add ecx, 8
|           0x004017c6      3d             invalid
..

/ 9: fcn2.0x004017c0 ();
| 0x004017c0      51             push ecx
| 0x004017c1      89e1           mov ecx, esp
| 0x004017c3      83c108         add ecx, 8
| 0x004017c6      3d             invalid
\ 0x004017c7      0010           add byte [eax], dl
| // true: 0x004017dd  false: 0x004017cd

size: 12
0x004017c0 0x004017cc 00:0000 12 j 0x004017dd f 0x004017cd

/ 12: fcn2.0x004017c0 ();
|           0x004017c0      51             push ecx
|           0x004017c1      89e1           mov ecx, esp
|           0x004017c3      83c108         add ecx, 8
|           0x004017c6      3d00100000     cmp eax, 0x1000
\           0x004017cb      72             invalid

/ 12: fcn2.0x004017c0 ();
| 0x004017c0      51             push ecx
| 0x004017c1      89e1           mov ecx, esp
| 0x004017c3      83c108         add ecx, 8
| 0x004017c6      3d00100000     cmp eax, 0x1000
\ 0x004017cb      72             invalid
| // true: 0x004017dd  false: 0x004017cd
EOF
RUN

NAME=afcf
FILE=bins/elf/crackme0x05
CMDS=<<EOF
af@main
afcf main @ 0
afcf @ main
afcfj @ main
EOF
EXPECT=<<EOF
int main (int argc, char **argv, char **envp);
int main (int argc, char **argv, char **envp);
[{"name":"main","return":"int","args":[{"name":"argc","type":"int"},{"name":"argv","type":"char **"},{"name":"envp","type":"char **"}],"count":3}]
EOF
RUN

NAME=afcf (vars)
FILE=bins/elf/ls
CMDS=<<EOF
s 0x00013c70
af
afcf
afcfj
EOF
EXPECT=<<EOF
fcn.00013c70 (int64_t arg1, int64_t arg2, int64_t arg3);
[{"name":"fcn.00013c70","args":[{"name":"arg1","type":"int64_t"},{"name":"arg2","type":"int64_t"},{"name":"arg3","type":"int64_t"}],"count":3}]
EOF
RUN

NAME=float args keep their own sequence beside the integer one
FILE=malloc://64
ARGS=-a x86 -b 64
CMDS=<<EOF
wx 4889f04889d0f20f58c8c3 @ 0
af
afv
pdf~arg
EOF
EXPECT=<<EOF
arg int64_t arg1 @ rsi
arg int64_t arg2 @ rdx
arg double arg3 @ xmm0
arg double arg4 @ xmm1
/ 11: fcn.00000000 (int64_t arg1, int64_t arg2, double arg3, double arg4);
| `- args(rsi, rdx, xmm0, xmm1)
|           0x00000000      4889f0         mov rax, rsi                ; arg1
|           0x00000003      4889d0         mov rax, rdx                ; arg2
|           0x00000006      f20f58c8       addsd xmm1, xmm0            ; arg4
EOF
RUN

NAME=arm64 float args come from the v register sequence
FILE=malloc://64
ARGS=-a arm -b 64
CMDS=<<EOF
wx 0000669e2100669ec0035fd6 @ 0
af
afv
EOF
EXPECT=<<EOF
arg double arg1 @ d0
arg double arg2 @ d1
EOF
RUN

NAME=arm64 float args match the s register spelling of the v sequence
FILE=malloc://32
ARGS=-a arm -b 64
CMDS=<<EOF
wx 0000261ec0035fd6 @ 0
af
afv
EOF
EXPECT=<<EOF
arg float arg1 @ s0
EOF
RUN

NAME=arm64 float args take the width of their first read, through a v copy
FILE=malloc://1024
ARGS=-a arm -b 64
CMDS=<<EOF
wx 0000669e2100669ec0035fd6 @ 0
wx 0028221e2128631ec0035fd6 @ 0x20
wx 040000940000669ec0035fd6 @ 0x40
wx c0035fd6 @ 0x50
wx 281ca14e091ca04e2029291e0029601ec0035fd6 @ 0x60
wx 081ca04ec0035fd6 @ 0x80
wx 00d4214ec0035fd6 @ 0x100
wx 081ca04e400000b42100679e0029281ec0035fd6 @ 0x110
wx 081ca04e2800679e010000140029281ec0035fd6 @ 0x130
wx 091ca04e2021211ec0035fd6 @ 0x150
wx 0000261e0100669ec0035fd6 @ 0x170
wx 081ca04e001da84eaeffff97c0035fd6 @ 0x190
wx 081ca04eabffff970029281ec0035fd6 @ 0x1a0
wx 011ca04ea7ffff972028211ec0035fd6 @ 0x1b0
wx 081ca04e400000b4c0035fd60029281ec0035fd6 @ 0x1c0
wx 081ca04eabffff970029281ec0035fd6 @ 0x1e0
wx 081ca04e830100940029281ec0035fd6 @ 0x1f0
wx 081ca04e610000b492ffff97c0035fd60085284ec0035fd6 @ 0x200
wx 081ca04e20003fd60029281ec0035fd6 @ 0x220
af @ 0x50
af @ 0
af @ 0x20
af @ 0x40
af @ 0x60
af @ 0x80
af @ 0x100
af @ 0x110
af @ 0x130
af @ 0x150
af @ 0x170
af @ 0x190
af @ 0x1a0
af @ 0x1b0
af @ 0x1c0
af @ 0x1f0
af @ 0x200
af @ 0x220
afv @ 0
afv @ 0x20
afv @ 0x40
afv @ 0x60
afv @ 0x80
afv @ 0x100
afv @ 0x110
afv @ 0x130
afv @ 0x150
afv @ 0x170
afvR @ 0x170
afv @ 0x190
afv @ 0x1a0
afv @ 0x1b0
afv @ 0x1c0
afv @ 0x1f0
afv @ 0x200
afv @ 0x220
e anal.cc=golang
af @ 0x1e0
afv @ 0x1e0
EOF
EXPECT=<<EOF
arg double arg1 @ d0
arg double arg2 @ d1
arg float arg1 @ s0
arg double arg2 @ d1
arg float arg3 @ s2
arg double arg4 @ d3
arg float arg1 @ s0
arg double arg2 @ d1
arg double arg1 @ d0
arg uint8_t[16] arg1 @ v0
arg uint8_t[16] arg2 @ v1
arg int64_t arg1 @ x1
arg float arg2 @ s0
arg int64_t arg1 @ x1
arg double arg2 @ d0
arg float arg1 @ s0
arg float arg2 @ s1
arg float arg1 @ s0
      arg1  0x170,0x174
arg double arg1 @ d0
arg float arg1 @ s0
arg double arg1 @ d0
arg float arg1 @ s0
arg float arg1 @ s0
arg uint8_t[16] arg1 @ v0
arg double arg1 @ d0
arg double arg1 @ d0
EOF
RUN

NAME=arm64 copied float width follows the callee calling convention
FILE=malloc://128
ARGS=-a arm -b 64
CMDS=<<EOF
wx 081ca04e070000940029281ec0035fd6 @ 0
wx 2800679ec0035fd6 @ 0x20
wx 081ca04e070000940029281ec0035fd6 @ 0x40
wx c0035fd6 @ 0x60
af @ 0x20
afc golang @ 0x20
af @ 0x60
af @ 0
afv @ 0
e anal.cc=golang
af @ 0x40
afv @ 0x40
EOF
EXPECT=<<EOF
arg double arg1 @ d0
arg float arg1 @ s0
EOF
RUN

NAME=arm64 copied float width stops at a callee whose preserve list lacks the register
FILE=malloc://512
ARGS=-a arm -b 64
CMDS=<<EOF
wx c0035fd6 @ 0x50
wx 081ca04eabffff970029281ec0035fd6 @ 0x1a0
k anal/cc/cc.golang.preserve=x19
af @ 0x50
afc golang @ 0x50
af @ 0x1a0
afv @ 0x1a0
EOF
EXPECT=<<EOF
arg double arg1 @ d0
EOF
RUN

NAME=arm64 vector width is not taken from a preserved register after a call
FILE=malloc://64
ARGS=-a arm -b 64
CMDS=<<EOF
wx 081ca04e0700009400d5284ec0035fd6 @ 0
wx e81f184ec0035fd6 @ 0x20
af @ 0x20
af @ 0
afv @ 0
EOF
EXPECT=<<EOF
arg double arg1 @ d0
EOF
RUN

NAME=arm64 fp arithmetic, conversions and compares read and write their registers
FILE=malloc://512
ARGS=-a arm -b 64
CMDS=<<EOF
wx 1038611e5190431fb29c661fc0035fd6 @ 0x0
wx 3088621ec0035fd6 @ 0x40
wx 1028611e5110631fc0035fd6 @ 0x80
wx 3040611ec0035fd6 @ 0xc0
wx 1040621e2900789e4a00799e7100629e9200639ec0035fd6 @ 0x100
wx 0900649e2a00659e4b00709e6c00719e8d00609eae00619ecf00689ef000699ec0035fd6 @ 0x140
wx 1020611e4004631e9414651ee0d79f1ac0035fd6 @ 0x180
wx 0100629e2008611e4100789e20040091c0035fd6 @ 0x1c0
af @ 0x0
af @ 0x40
af @ 0x80
af @ 0xc0
af @ 0x100
af @ 0x140
af @ 0x180
af @ 0x1c0
afv @ 0x0
?e --
afv @ 0x40
?e --
afv @ 0x80
?e --
afv @ 0xc0
?e --
afv @ 0x100
?e --
afv @ 0x140
?e --
afv @ 0x180
?e --
afv @ 0x1c0
EOF
EXPECT=<<EOF
arg double arg1 @ d0
arg double arg2 @ d1
arg double arg3 @ d2
arg double arg4 @ d3
arg double arg5 @ d4
arg double arg6 @ d5
arg double arg7 @ d6
arg double arg8 @ d7
--
arg double arg1 @ d1
arg double arg2 @ d2
--
arg double arg1 @ d0
arg double arg2 @ d1
arg double arg3 @ d2
arg double arg4 @ d3
arg double arg5 @ d4
--
arg double arg1 @ d1
--
arg int64_t arg1 @ x3
arg int64_t arg2 @ x4
arg double arg3 @ d0
arg double arg4 @ d1
arg double arg5 @ d2
--
arg double arg1 @ d0
arg double arg2 @ d1
arg double arg3 @ d2
arg double arg4 @ d3
arg double arg5 @ d4
arg double arg6 @ d5
arg double arg7 @ d6
arg double arg8 @ d7
--
arg double arg1 @ d0
arg double arg2 @ d1
arg double arg3 @ d2
arg double arg4 @ d3
arg double arg5 @ d4
arg double arg6 @ d5
--
arg int64_t arg1 @ x0
arg double arg2 @ d2
EOF
RUN

NAME=arm64 d0 read after a call is not an argument
FILE=malloc://64
ARGS=-a arm -b 64
CMDS=<<EOF
wx 040000940000669ec0035fd6 @ 0
wx c0035fd6 @ 0x10
af @ 0x10
af @ 0
afv @ 0
EOF
EXPECT=<<EOF
EOF
RUN

NAME=float args are recovered when no integer argument is passed
FILE=malloc://64
ARGS=-a x86 -b 64
CMDS=<<EOF
wx f20f58c8c3 @ 0
af
afv
EOF
EXPECT=<<EOF
arg double arg1 @ xmm0
arg double arg2 @ xmm1
EOF
RUN

NAME=xmm0 read after a call is not an argument
FILE=malloc://32
ARGS=-a x86 -b 64
CMDS=<<EOF
wx e80b000000f20f59c0c3 @ 0
wx c3 @ 0x10
af @ 0x10
af @ 0
afv @ 0
EOF
EXPECT=<<EOF
EOF
RUN

NAME=float args afli
FILE=bins/elf/float_point
CMDS=<<EOF
aa
afi sym.sum_float
EOF
EXPECT=<<EOF
#
addr: 0x00001119
name: sym.sum_float
size: 26
is-pure: true
realsz: 26
stackframe: 8
callconv: amd64
cyclic-cost: 10
cyclomatic-complexity: 1
bits: 64
type: sym [NEW]
num-bbs: 1
num-instrs: 8
edges: 0
minaddr: 0x00001119
maxaddr: 0x00001133
is-lineal: true
end-bbs: 1
maxbbins: 8
midbbins: 8.00
ratbbins: 1.00
noreturn: false
recursive: false
in-degree: 1
out-degree: 0
locals: 2
args: 2

EOF
RUN

NAME=double args afli
FILE=bins/elf/float_point
CMDS=<<EOF
aa
afi sym.sum_double
afv @ sym.sum_double
EOF
EXPECT=<<EOF
#
addr: 0x00001133
name: sym.sum_double
size: 26
is-pure: true
realsz: 26
stackframe: 8
callconv: amd64
cyclic-cost: 10
cyclomatic-complexity: 1
bits: 64
type: sym [NEW]
num-bbs: 1
num-instrs: 8
edges: 0
minaddr: 0x00001133
maxaddr: 0x0000114d
is-lineal: true
end-bbs: 1
maxbbins: 8
midbbins: 8.00
ratbbins: 1.00
noreturn: false
recursive: false
in-degree: 1
out-degree: 0
locals: 2
args: 2

arg double arg1 @ xmm0
arg double arg2 @ xmm1
var int64_t var_8h @ rbp-0x8
var int64_t var_10h @ rbp-0x10
EOF
RUN

NAME=afbt help
FILE=-
CMDS=afbt?
EXPECT=<<EOF
| afbt [tableaddr] [elem_sz] [count] [seg]  analyze function jumptable
EOF
RUN

NAME=afbt invalid suffix
FILE=-
CMDS=<<EOF
afbtx
s 0
EOF
EXPECT_ERR=<<EOF
ERROR: Invalid `x` subcommand, try `afbt?`
EOF
RUN

NAME=afbt display modes reject args
FILE=-
CMDS=<<EOF
afbtj tbl=0x10
afbt* tbl=0x10
s 0
EOF
EXPECT_ERR=<<EOF
ERROR: Invalid `j` subcommand, try `afbt?`
ERROR: Invalid `*` subcommand, try `afbt?`
EOF
RUN

NAME=duplicate af+
FILE=-
CMDS=<<EOF
af+ 0x1337 func
af+ 0x1337 func
af+ 0x1337 func
afl
EOF
EXPECT=<<EOF
0x00001337    0      0 func
EOF
EXPECT_ERR=<<EOF
ERROR: Cannot add dupped function 'func' at 0x00001337
ERROR: Cannot add dupped function 'func' at 0x00001337
EOF
RUN

NAME=function naming
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
wx c3c3c3c3c3c3c3c3c3
f sym.some_func @ 0
f sym.some_other_func @ 1
f a @ 2
f aa @ 3
f aaa @ 4
f aaaa @ 5
f sym @ 6
f sym. @ 7
f sym.b @ 8
e asm.flags.real=0
af @@ *
afl
?e --
af- @@ *
afl
?e --
e asm.flags.real=1
af @@ *
afl
EOF
EXPECT=<<EOF
0x00000000    1      1 sym.some_func
0x00000001    1      1 sym.some_other_func
0x00000002    1      1 a
0x00000003    1      1 aa
0x00000004    1      1 aaa
0x00000005    1      1 aaaa
0x00000006    1      1 sym
0x00000007    1      1 sym.
0x00000008    1      1 sym.b
--
--
0x00000000    1      1 sym.some_func
0x00000001    1      1 sym.some_other_func
0x00000002    1      1 a
0x00000003    1      1 aa
0x00000004    1      1 aaa
0x00000005    1      1 aaaa
0x00000006    1      1 sym
0x00000007    1      1 sym.
0x00000008    1      1 sym.b
EOF
RUN

NAME=af skips symbols
ARGS=-ebin.dbginfo=false
FILE=bins/elf/analysis/guess-number-riscv64
CMDS=<<EOF
af @ sym.fstatat
af @ sym.__syscall_error
afl
EOF
EXPECT=<<EOF
0x0001f8b8    2     20 sym.fstatat
0x0001f7cc    1     48 sym.__syscall_error
0x00021484    1      8 sym.__errno
EOF
RUN

NAME=af with custom sym.il name
FILE=bins/mach0/ls-m1
ARGS=-a arm -b 64
CMDS=<<EOF
sn
sn
s
f sym.il.piltrafilla
af
pd 2
EOF
EXPECT=<<EOF
0x1000047a8
            ;-- func.1000047a8:
/ 728: sym.il.piltrafilla (int64_t arg1, int64_t arg2, int64_t arg3);
| `- args(x0, x1, x2) vars(10:sp[0x8..0x50])
|           0x1000047a8      7f2303d5       pacibsp
|           0x1000047ac      fc6fbaa9       stp x28, x27, [sp, -0x60]!
EOF
RUN

NAME=af keeps the frame size when analysis continues in a second pass
FILE=malloc://64
ARGS=-a x86 -b 64 -e anal.bb.maxsize=8
CMDS=<<EOF
wx 554889e54883ec404883ec104889ec5dc3
af
afi~stackframe
EOF
EXPECT=<<EOF
stackframe: 88
EOF
RUN

NAME=af keeps the frame size when a tail call continues the function
FILE=malloc://64
ARGS=-a x86 -b 64
CMDS=<<EOF
wx 554889e54883ec40eb00554889e55dc3
af @ 0xa
f- fcn.0000000a
af @ 0
afi @ 0~name,stackframe
EOF
EXPECT=<<EOF
name: fcn.00000000
stackframe: 72
EOF
RUN

NAME=af warns on non-executable map
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e scr.null=true
o malloc://512 0x10000
e scr.null=false
s 0x10000
wx 554889e5c3
af
afl~?
ompg +x
af
afl~?
EOF
EXPECT=<<EOF
0
1
EOF
EXPECT_ERR=
RUN

NAME=af analyzes non-executable map with anal.in=io.maps
FILE=-
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e scr.null=true
o malloc://512 0x10000
e scr.null=false
s 0x10000
wx 554889e5c3
e anal.in=io.maps
af
afl~?
EOF
EXPECT=<<EOF
1
EOF
RUN

NAME=af reads a block again after cmd.fcn.new writes it
FILE=malloc://256
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
wx 7401c3e918000000cc @ 0
wx 554889e5c3 @ 0x20
"e cmd.fcn.new=wx 90c3 @ $$-0x1e"
af @ 0
afb @ 0
EOF
EXPECT=<<EOF
0x00000000 0x00000002 00:0000 2 j 0x00000003 f 0x00000002
0x00000002 0x00000003 00:0000 1 j 0x00000003
0x00000003 0x00000008 00:0000 5 j 0x00000020
EOF
RUN

NAME=afia set, unset and query function attributes
FILE=malloc://256
CMDS=<<EOF
e asm.arch=arm
e asm.bits=64
af+ 0x10 fcn.attr
afb+ 0x10 0x10 8
s 0x10
afia~inline,noreturn
afia+ inline,noreturn
afia~inline,noreturn
afiaj
afia- inline
afia~inline
afia- noreturn
afia~noreturn
EOF
EXPECT=<<EOF
  noreturn  false
  inline    false
  noreturn  true
  inline    true
{"noreturn":true,"inline":true,"pure":true,"variadic":false}
  inline    false
  noreturn  false
EOF
RUN

NAME=aflj reports inline per function after setting and clearing
FILE=malloc://256
ARGS=-a arm -b 64
CMDS=<<EOF
af+ 0x10 fcn.one
afb+ 0x10 0x10 8
af+ 0x20 fcn.two
afb+ 0x20 0x20 8
s 0x20
aflj~{[0].inline}
aflj~{[1].inline}
afia+ inline @ 0x10
aflj~{[0].inline}
aflj~{[1].inline}
afia- inline @ 0x10
aflj~{[0].inline}
EOF
EXPECT=<<EOF
false
false
true
false
false
EOF
RUN

NAME=afia rejects unknown and read-only attributes
FILE=malloc://256
CMDS=<<EOF
e asm.arch=arm
e asm.bits=64
af+ 0x10 fcn.attr
afb+ 0x10 0x10 8
s 0x10
"afia+ pure"
"afia+ bogus"
EOF
EXPECT=<<EOF
EOF
EXPECT_ERR=<<EOF
ERROR: Attribute 'pure' is read-only: the function does not read or write outside state (computed)
ERROR: Unknown function attribute 'bogus'
EOF
RUN

NAME=afl script preserves inline at its function address
FILE=malloc://256
ARGS=-a arm -b 64
CMDS=<<EOF
mkdir .tmp
af+ 0x10 fcn.one
afb+ 0x10 0x10 4
af+ 0x20 fcn.two
afb+ 0x20 0x20 4
afia+ inline @ 0x10
afl*~afia > .tmp/afia-legacy.r2
afia- inline @ 0x10
s 0x20
. .tmp/afia-legacy.r2
afia @ 0x10~inline
afia @ 0x20~inline
rm .tmp/afia-legacy.r2
EOF
EXPECT=<<EOF
  inline    true
  inline    false
EOF
RUN
