Skip to content

Commit c64a77f

Browse files
authored
adds several new Primus Lisp primitives and new instructions (#1410)
* adds several new Primus Lisp primitives and new instructions This commit adds three new primitives that could be used in definition instruction semantics: - invoke-subroutine, especially useful for intrinsic calls - empty, which denotes empty semantics, useful for nops - special to denote special semantics, like `hlt` It also implements semantics for several missing semantics (detected with `--print-missing`), mostly nops, but there's one significant finding - the `popa` (POPA32 in llvm parlance) instruction from x86, which was surprisingly missing. * adds support for specials in the BIL effect analyzer this enables proper handling of specially encoded calls and intrinsics
1 parent b80212b commit c64a77f

File tree

10 files changed

+100
-8
lines changed

10 files changed

+100
-8
lines changed

lib/bap_disasm/bap_disasm_insn.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ module Analyzer = struct
229229
let conditional v = jump ~cond:true v in
230230
let indirect f v = f { v with indirect=true } in
231231
object
232-
inherit [Effects.t * vis] Stmt.visitor
232+
inherit [Effects.t * vis] Stmt.visitor as super
233233
method! enter_store ~mem:_ ~addr:_ ~exp:_ _ _ (effs,jumps) =
234234
Set.add effs `May_store,jumps
235235
method! enter_load ~mem:_ ~addr:_ _ _ (effs,jumps) =
@@ -239,6 +239,9 @@ module Analyzer = struct
239239
| Bil.Int _ -> jump jumps
240240
| _ when under_condition -> indirect conditional jumps
241241
| _ -> indirect jump jumps
242+
method! enter_stmt s (effs,jumps) = match Bil.(decode call s) with
243+
| None -> super#enter_stmt s (effs,jumps)
244+
| Some _ -> Effects.add effs `Call, jumps
242245
end
243246

244247
let run bil =
@@ -258,9 +261,8 @@ let derive_props ?bil insn =
258261
let is = Insn.is insn in
259262
let is_bil = if Option.is_some bil
260263
then Analyzer.Effects.mem bil_effects else is in
261-
(* those two are the only which we can't get from the BIL semantics *)
262264
let is_return = is `Return in
263-
let is_call = is `Call in
265+
let is_call = is_bil `Call || is `Call in
264266
let is_conditional_jump = is_bil `Conditional_branch in
265267
let is_jump = is_conditional_jump || is_bil `Unconditional_branch in
266268
let is_indirect_jump = is_bil `Indirect_branch in

oasis/powerpc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Library powerpc_plugin
4040
Powerpc_shift,
4141
Powerpc_store,
4242
Powerpc_sub
43+
DataFiles: semantics/*.lisp ($datadir/bap/primus/semantics)
4344
XMETAExtraLines: tags="powerpc, lifter"
4445

4546
Library powerpc_test

oasis/x86

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Library x86_plugin
7575
X86_legacy_fp_lifter,
7676
X86_legacy_bil_register,
7777
X86_legacy_operands
78+
DataFiles: semantics/*.lisp ($datadir/bap/primus/semantics)
7879
XMETAExtraLines: tags="disassembler, lifter, x86, abi"
7980

8081
Library x86_test

plugins/arm/semantics/aarch64.lisp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,10 @@
250250
(defun Bcc (cnd off)
251251
(when (condition-holds cnd)
252252
(relative-jump off)))
253+
254+
(defun HINT (_)
255+
(empty))
256+
257+
258+
(defun UDF (exn)
259+
(special :undefined-instruction))
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(declare (context (target powerpc)))
2+
3+
(defpackage powerpc (:use core target))
4+
(defpackage llvm-powerpc32 (:use powerpc))
5+
6+
7+
(defun NOP ()
8+
(empty))

plugins/primus_lisp/primus_lisp_semantic_primitives.ml

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ let export = Primus.Lisp.Type.Spec.[
144144
machine word.";
145145

146146
"exec-addr", one int @-> any,
147-
"(exec-addr ADDR) transfers control flow to ADDR.";
147+
"(exec-addr ADDR) transfers control to ADDR.";
148+
149+
"invoke-subroutine", one sym @-> any,
150+
"(invoke-subroutine NAME) passes control to the subroutine NAME.";
148151

149152
"goto-subinstruction", one int @-> any,
150153
"(goto-subinstruction N) transfers control flow to a
@@ -188,7 +191,7 @@ let export = Primus.Lisp.Type.Spec.[
188191
"get-current-program-counter", unit @-> int,
189192
"(get-current-program-counter) is an alias to (get-program-counter)";
190193

191-
"set-symbol-value", tuple [int; a] @-> a,
194+
"set-symbol-value", tuple [any; a] @-> a,
192195
"(set-symbol-value S X) sets the value of the symbol S to X.
193196
Returns X";
194197

@@ -229,6 +232,11 @@ let export = Primus.Lisp.Type.Spec.[
229232
"nth", (one any @-> bool),
230233
"(nth N X) returns the Nth bit of X. N must be static. \
231234
The function is equivalent to (select N X)";
235+
"empty", (unit @-> any),
236+
"(empty) denotes an instruction that does nothing, i.e., a nop.";
237+
"special", (one sym @-> any),
238+
"(special :NAME) produces a special effect denoted by the keyword :NAME.
239+
The effect will be reified into the to the special:name subroutine. ";
232240
]
233241

234242
type KB.conflict += Illformed of string
@@ -433,6 +441,9 @@ module Primitives(CT : Theory.Core)(T : Target) = struct
433441
let memory eff res =
434442
full CT.(blk null (perform eff) skip) res
435443

444+
let nop () =
445+
CT.perform Theory.Effect.Sort.bot
446+
436447
let loads = memory Theory.Effect.Sort.rmem
437448
let stores = memory Theory.Effect.Sort.wmem
438449
let loads = pure
@@ -620,6 +631,20 @@ module Primitives(CT : Theory.Core)(T : Target) = struct
620631
| Some _ -> true_
621632
| _ -> false_
622633

634+
let is_keyword = String.is_prefix ~prefix:":"
635+
636+
let special dst =
637+
require_symbol dst @@ fun dst ->
638+
if is_keyword dst then
639+
let* dst = Theory.Label.for_name ("special"^dst) in
640+
CT.goto dst
641+
else illformed "special requires a keyword as the tag, e.g., :hlt"
642+
643+
let invoke_subroutine dst =
644+
require_symbol dst @@ fun dst ->
645+
let* dst = Theory.Label.for_name dst in
646+
CT.goto dst
647+
623648
let mk_cast t cast xs =
624649
binary xs @@ fun sz x ->
625650
to_sort sz >>= fun s ->
@@ -784,12 +809,12 @@ module Primitives(CT : Theory.Core)(T : Target) = struct
784809
| "extract",xs -> pure@@extract xs
785810
| "concat", xs -> pure@@concat xs
786811
| ("select"|"nth"),xs -> pure@@select s xs
812+
| "empty",[] -> nop ()
813+
| "special",[dst] -> ctrl@@special dst
814+
| "invoke-subroutine",[dst] -> ctrl@@invoke_subroutine dst
787815
| _ -> !!nothing
788816
end
789817

790-
791-
792-
793818
module Lisp = Primus.Lisp.Semantics
794819

795820
let provide () =

plugins/riscv/semantics/riscv.lisp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,10 @@
214214

215215
(defun C_BNEZ (rs1 off)
216216
(conditional-jump (not (is-zero rs1)) off))
217+
218+
219+
(defun C_NOP ()
220+
(empty))
221+
222+
(defun NOP ()
223+
(empty))

plugins/x86/semantics/x86-32.lisp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
(declare (context (target i386) (bits 32)))
2+
3+
(require x86-common)
4+
(in-package x86-32)
5+
6+
(defun pop (dst)
7+
(set$ dst (load-word ESP))
8+
(+= ESP 4))
9+
10+
(defun POPA32 ()
11+
(pop 'EDI)
12+
(pop 'ESI)
13+
(pop 'EBP)
14+
(+= ESP 4)
15+
(pop 'EBX)
16+
(pop 'EDX)
17+
(pop 'ECX)
18+
(pop 'EAX))

plugins/x86/semantics/x86-64.lisp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(declare (context (target amd 64) (bits 64)))
2+
(require x86-common)

plugins/x86/semantics/x86-common.lisp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(declare (context (target x86)))
2+
3+
(defpackage x86-common (:use core target))
4+
(defpackage x86-32 (:use x86-common))
5+
(defpackage x86-64 (:use x86-common))
6+
(defpackage llvm-x86 (:use x86-32))
7+
(defpackage llvm-x86_64 (:use x86-64))
8+
9+
(in-package x86-common)
10+
11+
(defun HLT ()
12+
(special :hlt))
13+
14+
(defun NOOP ()
15+
(empty))
16+
17+
(defun NOOPL (_ _ _ _ _)
18+
(empty))
19+
20+
(defun NOOPW (_ _ _ _ _)
21+
(empty))

0 commit comments

Comments
 (0)