Skip to content

Commit 8a5796c

Browse files
authored
fixes and improves aarch64 lifter (#1351)
1) adds proper aarch64 language ids for the ghidra backend 2) adds about 20 more instructions 3) dealiases R31 and ZR, WZR, and XZR 4) adds the full set of tests (that use symbolic executor) 5) fixes instructions with 32-bit operands, the new `setw` macro now correctly zeros the uppert 32 bits. Also some number of quality of life changes: 1) `--primus-lisp-semantics` now fails with a clear message when the passed argument doesn't name a folder (previously it was silently ignoring it). 2) moves arm-wide operations to `arm-bits` 3) allows to repeat of the `--primus-lisp-load` parameter, to make it easier to use it in scripts and recipes.
1 parent a733374 commit 8a5796c

File tree

5 files changed

+108
-52
lines changed

5 files changed

+108
-52
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ testsuite:
5555
git clone https://github.com/BinaryAnalysisPlatform/bap-testsuite.git testsuite
5656

5757
check: testsuite
58-
make REVISION=3720beda -C testsuite
58+
make REVISION=f8af868e4f61 -C testsuite
5959

6060
.PHONY: indent check-style status-clean
6161

lib/arm/arm_target.ml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ let (.$()) = List.nth_exn
105105

106106
let aliases =
107107
xs @< ws @< qs @< ds @< ss @< hs @< bs
108-
@<[fp64; lr64; sp64; zr; zr64]
108+
@<[fp64; lr64; sp64; zr64]
109109
@<[sp32; zr32]
110110

111111
let varsv8 = rs @< flagsv8 @< [datav8]
@@ -137,7 +137,6 @@ let aliasing = Theory.Alias.[
137137
def lr64 [reg xs.$(30)];
138138
def sp64 [reg xs.$(31)];
139139
def sp64 [unk; reg sp32];
140-
def zr [reg xs.$(31)];
141140
def zr [reg zr64];
142141
def zr [unk; reg zr32];
143142
];
@@ -153,10 +152,6 @@ let aliasing = Theory.Alias.[
153152

154153
let parent = CT.Target.declare ~package "arm"
155154

156-
module type v4 = sig
157-
end
158-
159-
160155
module type ARM = sig
161156
val endianness : CT.endianness
162157
val parent : CT.Target.t
@@ -511,9 +506,8 @@ let is_little t = Theory.Target.endianness t = Theory.Endianness.le
511506
let register_pcode () =
512507
Dis.register pcode @@ fun t ->
513508
let triple = match is_64bit t,is_little t,is_big t with
514-
| true,true,_ -> "ARM:LE:32:v8"
515-
| true,_,true -> "ARM:BE:32:v8"
516-
| true,_,_ -> "ARM:LEBE:32:v8LEInstruction"
509+
| true,true,_ -> "AARCH64:LE:64:v8A"
510+
| true,_,_ -> "AARCH64:BE:64:v8A"
517511
| false,true,_ -> "ARM:LE:32:v7"
518512
| false,_,true -> "ARM:BE:32:v7"
519513
| false,_,_ -> "ARM:LEBE:32:v7LEInstruction" in

plugins/arm/semantics/aarch64.lisp

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
(declare (context (target arm armv8-a+le)))
2+
13
(require bits)
24
(require arm-bits)
35

4-
(declare (context (target armv8-a+le)))
56
(defpackage aarch64 (:use core target arm))
67
(defpackage llvm-aarch64 (:use aarch64))
78

@@ -13,7 +14,17 @@
1314
(set$ dst (lshift imm pos)))
1415

1516
(defun MOVZWi (dst imm pos)
16-
(set$ dst (lshift imm pos)))
17+
(setw dst (lshift imm pos)))
18+
19+
(defun MOVNWi (dst imm off)
20+
(setw dst (lnot (lshift imm off))))
21+
22+
(defmacro MOVK*i (dst reg imm off)
23+
(let ((mask (lnot (lshift (- (lshift 1 16) 1) off))))
24+
(set$ dst (logor (logand reg mask) (lshift imm off)))))
25+
26+
(defun MOVKWi (dst reg imm off) (MOVK*i dst reg imm off))
27+
(defun MOVKXi (dst reg imm off) (MOVK*i dst reg imm off))
1728

1829
(defun ADDXri (dst src imm off)
1930
(set$ dst (+ src (lshift imm off))))
@@ -27,49 +38,75 @@
2738
(load-hword (+ base (lshift off 2))))))
2839

2940
(defun LDRWui (dst reg off)
30-
(set$ dst
41+
(setw dst
3142
(cast-unsigned (word) (load-hword (+ reg (lshift off 2))))))
3243

3344
(defun LDRBBui (dst reg off)
45+
(setw dst
46+
(cast-unsigned (word) (load-byte (+ reg off)))))
47+
48+
(defun LDRBBroX (dst reg off _ _)
3449
(set$ dst
3550
(cast-unsigned (word) (load-byte (+ reg off)))))
3651

37-
(defmacro make-BFM (cast xd xr ir is)
52+
(defmacro make-BFM (set cast xd xr ir is)
3853
(let ((rs (word)))
3954
(if (< is ir)
4055
(if (and (/= is (- rs 1)) (= (+ is 1) ir))
41-
(set$ xd (lshift xr (- rs ir)))
42-
(set$ xd (lshift
56+
(set xd (lshift xr (- rs ir)))
57+
(set xd (lshift
4358
(cast rs (extract is 0 xr))
4459
(- rs ir))))
4560
(if (= is (- rs 1))
46-
(set$ xd (rshift xr ir))
47-
(set$ xd (cast rs (extract is ir xr)))))))
61+
(set xd (rshift xr ir))
62+
(set xd (cast rs (extract is ir xr)))))))
4863

4964
(defun UBFMXri (xd xr ir is)
50-
(make-BFM cast-unsigned xd xr ir is))
65+
(make-BFM set$ cast-unsigned xd xr ir is))
66+
67+
(defun UBFMWri (xd xr ir is)
68+
(make-BFM setw cast-unsigned xd xr ir is))
5169

5270
(defun SBFMXri (xd xr ir is)
53-
(make-BFM cast-signed xd xr ir is))
71+
(make-BFM set$ cast-signed xd xr ir is))
72+
73+
(defun SBFMWri (xd xr ir is)
74+
(make-BFM setw cast-signed xd xr ir is))
5475

55-
(defun ORRXrs (rd rn rm is)
56-
(set$ rd (logor rn (shifted rm is))))
76+
(defmacro ORN*rs (set rd rn rm is)
77+
(set rd (logor rn (lnot (lshift rm is)))))
78+
79+
(defun ORNWrs (rd rn rm is) (ORN*rs setw rd rn rm is))
80+
(defun ORNXrs (rd rn rm is) (ORN*rs set$ rd rn rm is))
81+
82+
(defmacro log*?rs (set op rd rn rm is)
83+
(set rd (op rn (shifted rm is))))
84+
85+
(defun ORRWrs (rd rn rm is) (log*?rs setw logor rd rn rm is))
86+
(defun EORWrs (rd rn rm is) (log*?rs setw logxor rd rn rm is))
87+
(defun ANDWrs (rd rn rm is) (log*?rs setw logand rd rn rm is))
88+
(defun ORRXrs (rd rn rm is) (log*?rs set$ logor rd rn rm is))
89+
(defun EORXrs (rd rn rm is) (log*?rs set$ logxor rd rn rm is))
90+
(defun ANDXrs (rd rn rm is) (log*?rs set$ logand rd rn rm is))
91+
92+
93+
(defun ANDWri (dst rn imm)
94+
(setw dst (logand rn imm)))
5795

58-
(defun ORRWrs (rd rn rm is)
59-
(set$ rd
60-
(logor rn
61-
(shifted rm is))))
6296

6397
(defun ADRP (dst imm)
6498
(set$ dst (+
6599
(logand (get-program-counter) (lshift -1 12))
66100
(cast-signed (word) (lshift imm 12)))))
67101

68102
(defun ADDWrs (dst r1 v s)
69-
(set$ dst (+ r1 (lshift v s))))
103+
(setw dst (+ r1 (lshift v s))))
104+
105+
(defun SUBWrs (dst r1 v s)
106+
(setw dst (- r1 (lshift v s))))
70107

71108
(defun ADDWri (dst r1 imm s)
72-
(set$ dst (+ r1 (lshift imm s))))
109+
(setw dst (+ r1 (lshift imm s))))
73110

74111

75112
(defun SUBXrx64 (rd rn rm off)
@@ -79,12 +116,12 @@
79116
(add-with-carry rd rn (lnot (shifted rm off)) 1))
80117

81118
(defun SUBSWrs (rd rn rm off)
82-
(add-with-carry
119+
(add-with-carry/clear-base
83120
rd
84121
rn (lnot (shifted rm off)) 1))
85122

86123
(defun SUBSWri (rd rn imm off)
87-
(add-with-carry rd rn (lnot (lshift imm off)) 1))
124+
(add-with-carry/clear-base rd rn (lnot (lshift imm off)) 1))
88125

89126

90127
(defun SUBSXri (rd rn imm off)
@@ -97,7 +134,7 @@
97134
(set$ rd (- rn (lshift imm off))))
98135

99136
(defun SUBWri (rd rn imm off)
100-
(set$ rd (- rn (lshift imm off))))
137+
(setw rd (- rn (lshift imm off))))
101138

102139
(defun ADDXrs (rd rn rm off)
103140
(set$ rd (+ rn (shifted rm off))))
@@ -138,6 +175,11 @@
138175
(store-word (+ dst off (sizeof word)) t2)
139176
(set$ dst (+ dst off))))
140177

178+
(defun STPXi (t1 t2 base off)
179+
(let ((off (lshift off 4)))
180+
(store-word base (+ base off))
181+
(store-word base (+ base off (sizeof word)))))
182+
141183
(defun LDPXpost (dst r1 r2 base off)
142184
(let ((off (lshift off 3)))
143185
(set$ r1 (load-word base))
@@ -208,21 +250,3 @@
208250
(defun Bcc (cnd off)
209251
(when (condition-holds cnd)
210252
(relative-jump off)))
211-
212-
(defun condition-holds (cnd)
213-
(case cnd
214-
0b0000 ZF
215-
0b0001 (lnot ZF)
216-
0b0010 CF
217-
0b0010 (lnot CF)
218-
0b0100 NF
219-
0b0101 (lnot NF)
220-
0b0110 VF
221-
0b0111 (lnot VF)
222-
0b1000 (logand CF (lnot ZF))
223-
0b1001 (logor (lnot CF) ZF)
224-
0b1010 (= NF VF)
225-
0b1011 (/= NF VF)
226-
0b1100 (logand (= NF VF) (= ZF 0))
227-
0b1101 (logor (/= NF VF) (/= ZF 0))
228-
true))

plugins/arm/semantics/arm-bits.lisp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111
(set CF (carry r x y))
1212
(set$ rd r)))
1313

14+
(defun add-with-carry/clear-base (rd x y c)
15+
(let ((r (+ c y x)))
16+
(set NF (msb r))
17+
(set VF (overflow r x y))
18+
(set ZF (is-zero r))
19+
(set CF (carry r x y))
20+
(clear-base rd)
21+
(set$ rd r)))
22+
23+
24+
1425
(defun logandnot (rd rn)
1526
(logand rd (lnot rn)))
1627

@@ -20,3 +31,30 @@
2031
(set$ rd (shift r rm))
2132
(set ZF (is-zero rd))
2233
(set NF (msb rd))))
34+
35+
(defun condition-holds (cnd)
36+
(case cnd
37+
0b0000 ZF
38+
0b0001 (lnot ZF)
39+
0b0010 CF
40+
0b0010 (lnot CF)
41+
0b0100 NF
42+
0b0101 (lnot NF)
43+
0b0110 VF
44+
0b0111 (lnot VF)
45+
0b1000 (logand CF (lnot ZF))
46+
0b1001 (logor (lnot CF) ZF)
47+
0b1010 (= NF VF)
48+
0b1011 (/= NF VF)
49+
0b1100 (logand (= NF VF) (lnot ZF))
50+
0b1101 (logor (/= NF VF) ZF)
51+
true))
52+
53+
(defun clear-base (reg)
54+
(set$ (alias-base-register reg) 0))
55+
56+
(defmacro setw (reg val)
57+
"(set Wx V) sets a Wx register clearing the upper 32 bits."
58+
(let ((res val))
59+
(clear-base reg)
60+
(set$ reg res)))

plugins/primus_lisp/primus_lisp_main.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ let () =
376376
Config.(param (list dir) ~doc:"paths to lisp libraries" "add") in
377377

378378
let features =
379-
Config.(param (list string) ~doc:"load specified module" "load"
380-
~default:["posix"]) in
379+
Config.(param_all (list string) ~doc:"load specified module" "load"
380+
~default:[["posix"]]) in
381381

382382
let semantics =
383383
let doc = sprintf "prepend the specified folders to the list of
@@ -413,7 +413,7 @@ let () =
413413
if !!enable_typecheck then
414414
Project.register_pass' ~deps:["api"] ~autorun:true typecheck;
415415
let paths = [Filename.current_dir_name] @ !!libs @ library_paths in
416-
let features = "core" :: !!features in
416+
let features = "core" :: List.concat !!features in
417417
Primus.Components.register_generic ~package:"bap" "lisp-type-checker"
418418
(module TypeErrorSummary)
419419
~desc:"Typechecks program and outputs the summary in the standard output.";

0 commit comments

Comments
 (0)