Skip to content

Commit 2af9d91

Browse files
authored
restructures powerpc targets and reimplements ppc32 eabi (#1526)
* revamps powerpc targets * reimplements powerpc abi
1 parent 4b9932b commit 2af9d91

File tree

6 files changed

+121
-137
lines changed

6 files changed

+121
-137
lines changed

.merlin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ B lib/bap_llvm
7373
B lib/regular
7474
B lib/text_tags
7575
B lib/knowledge
76-
76+
B lib/bap_powerpc
7777

7878
S lib/bap
7979
S lib/bap_main

lib/bap_powerpc/bap_powerpc_target.ml

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,14 @@ let bool = Theory.Bool.t
1919

2020
let reg t n = Theory.Var.define t n
2121

22-
let array t fmt size =
22+
let array ?(from=0) t fmt size =
2323
let fmt = Scanf.format_from_string fmt "%d" in
24-
List.init size ~f:(fun i -> reg t (sprintf fmt i))
24+
List.init size ~f:(fun i -> reg t (sprintf fmt (i+from)))
2525

2626
let untyped = List.map ~f:Theory.Var.forget
2727
let (@<) xs ys = untyped xs @ untyped ys
2828

29-
let name size order =
30-
let order = Theory.Endianness.name order in
31-
sprintf "powerpc%d+%s" size (KB.Name.unqualified order)
32-
33-
let parent = Theory.Target.declare ~package "powerpc"
29+
let parent = Theory.Target.declare ~package "powerpc-family"
3430

3531
let crflags =
3632
List.concat @@ List.init 8 ~f:(fun group ->
@@ -43,7 +39,7 @@ let flags = List.map ~f:(reg bool) [
4339
"C"; "FL"; "FE"; "FG"; "FU"
4440
] @ crflags
4541

46-
let define ?(parent=parent) ?nicknames bits endianness =
42+
let define ?(parent=parent) ?nicknames name bits endianness =
4743
let size = Theory.Bitv.size bits in
4844
let mems = Theory.Mem.define bits r8 in
4945
let data = Theory.Var.define mems "mem" in
@@ -53,7 +49,7 @@ let define ?(parent=parent) ?nicknames bits endianness =
5349
flags @<
5450
[reg bits "CTR"; reg bits "LR"; reg bits "TAR" ] @<
5551
[data] in
56-
Theory.Target.declare ~package (name size endianness)
52+
Theory.Target.declare ~package name
5753
~parent
5854
?nicknames
5955
~bits:size
@@ -74,36 +70,48 @@ let define ?(parent=parent) ?nicknames bits endianness =
7470
[carry_flag], untyped@@[reg bool "CA"; reg bool "CA32"];
7571
[overflow_flag], untyped@@List.(["SO"; "OV"; "OV32"] >>| reg bool);
7672
[status; floating], untyped@@List.(["FL"; "FE"; "FG"; "FU"] >>| reg bool);
73+
[caller_saved], untyped [reg bits "R0"] @
74+
untyped (array bits ~from:3 "R%d" 10) @
75+
untyped (array r64 "F%d" 14);
76+
[callee_saved], untyped [reg bits "R1"] @
77+
untyped (array bits ~from:14 "R%d" 18) @
78+
untyped (array r64 ~from:14 "F%d" 18);
79+
[function_argument; integer], untyped (array bits ~from:3 "R%d" 8);
80+
[function_argument; floating], untyped (array bits ~from:1 "F%d" 8);
81+
[function_return; integer], untyped [reg bits "R3"; reg bits "R4"];
82+
[function_return; floating], untyped [reg r64 "F0"];
83+
[reserved], untyped@@[reg bits "R2"];
7784
]
7885

79-
let powerpc32bi = define r32 Theory.Endianness.bi
80-
~nicknames:["powerpc32bi"; "ppc32bi"]
86+
let powerpc32bi = define "powerpcbi" r32 Theory.Endianness.bi
87+
~nicknames:["powerpc32bi"; "ppc32bi"; "powerpc32+bi"]
8188

82-
let powerpc32eb = define r32 Theory.Endianness.eb
89+
let powerpc32eb = define "powerpc" r32 Theory.Endianness.eb
8390
~nicknames:[
84-
"powerpc"; "ppc"; "powerpc32"; "ppc32";
91+
"powerpc32+eb"; "ppc"; "powerpc32"; "ppc32";
8592
"powerpc32eb"; "powerpc32be"; "ppc32eb"; "ppc32be";
8693
"power"; "power32";
8794
]
88-
let powerpc32le = define r32 Theory.Endianness.le
95+
let powerpc32le = define "powerpcle" r32 Theory.Endianness.le
8996
~nicknames:[
90-
"powerpcle"; "ppcle"; "ppcel";
97+
"powerpc32+le"; "ppcle"; "ppcel";
9198
"powerpc32le"; "powerpc32el";
9299
"ppc32le"; "ppc32el"
93100
]
94101

95-
let powerpc64bi = define r64 Theory.Endianness.bi
96-
~nicknames:["powerpc64bi"; "power64bi"]
97-
let powerpc64eb = define r64 Theory.Endianness.eb
102+
let powerpc64bi = define "powerpc64bi" r64 Theory.Endianness.bi
103+
~nicknames:["powerpc64+bi"; "power64bi"]
104+
105+
let powerpc64eb = define "powerpc64" r64 Theory.Endianness.eb
98106
~nicknames:[
99-
"powerpc64"; "ppc64"; "power64";
107+
"powerpc64+bi"; "ppc64"; "power64";
100108
"powerpc64eb"; "powerpc64be";
101109
"ppc64eb"; "ppc64be";
102110
"power64eb"; "power64be"
103111
]
104-
let powerpc64le = define r64 Theory.Endianness.le
112+
let powerpc64le = define "powerpc64le" r64 Theory.Endianness.le
105113
~nicknames:[
106-
"powerpc64el"; "powerpc64le";
114+
"powerpc64el"; "powerpc64+le";
107115
"ppc64el"; "ppc64le";
108116
"power64el"; "power64le"
109117
]
@@ -115,35 +123,47 @@ let enable_loader () =
115123
let request =
116124
Ogre.request Image.Scheme.arch >>= fun arch ->
117125
Ogre.request Image.Scheme.is_little_endian >>= fun little ->
118-
Ogre.return (arch,little) in
126+
Ogre.request Image.Scheme.format >>= fun format ->
127+
Ogre.return (arch,little,format) in
119128
match Ogre.eval request doc with
120-
| Error _ -> None,None
129+
| Error _ -> None,None,None
121130
| Ok info -> info in
122131
KB.promise Theory.Unit.target @@ fun unit ->
123-
KB.collect Image.Spec.slot unit >>|
124-
request_info >>| function
125-
| Some "powerpc", None -> powerpc32bi
126-
| Some "powerpc64",None -> powerpc64bi
127-
| Some "powerpc",Some true -> powerpc32le
128-
| Some "powerpc64",Some true -> powerpc64le
129-
| Some "powerpc",Some false -> powerpc32eb
130-
| Some "powerpc64",Some false -> powerpc64eb
131-
| _ -> Theory.Target.unknown
132-
133-
134-
let mapped_powerpc = Map.of_alist_exn (module Theory.Target) [
135-
powerpc32eb, `ppc;
136-
powerpc64eb, `ppc64;
137-
powerpc64le, `ppc64le;
138-
]
132+
KB.collect Image.Spec.slot unit >>| request_info >>| fun (arch,is_little,format) ->
133+
let (abi,filetype) = match format with
134+
| Some "elf" -> Theory.Abi.gnu, Theory.Filetype.elf
135+
| Some "macho" -> Theory.Abi.gnu, Theory.Filetype.macho
136+
| _ -> Theory.Abi.unknown, Theory.Filetype.unknown in
137+
let parent = match arch, is_little with
138+
| Some "powerpc", (None|Some false) -> powerpc32eb
139+
| Some "powerpc64",(None|Some false) -> powerpc64eb
140+
| Some "powerpc",Some true -> powerpc32le
141+
| Some "powerpc64",Some true -> powerpc64le
142+
| _ -> Theory.Target.unknown in
143+
if Theory.Target.is_unknown parent then parent
144+
else Theory.Target.select ~strict:true ~parent ~filetype ~abi ()
145+
146+
147+
let register_subtargets () =
148+
[powerpc32eb; powerpc32le; powerpc64eb; powerpc64le] |>
149+
List.iter ~f:(fun parent ->
150+
Theory.Target.register parent
151+
~abis:Theory.Abi.[unknown; gnu]
152+
~systems:Theory.System.[unknown; linux; freebsd; openbsd; vxworks]
153+
~filetypes:Theory.Filetype.[unknown; elf; macho])
154+
139155

140156
let map_powerpc () =
141157
let open KB.Syntax in
142158
KB.promise Arch.unit_slot @@ fun unit ->
143-
KB.collect Theory.Unit.target unit >>|
144-
Map.find mapped_powerpc >>| function
145-
| Some arch -> arch
146-
| None -> `unknown
159+
KB.collect Theory.Unit.target unit >>| fun t ->
160+
if Theory.Target.belongs parent t then
161+
match Theory.Target.bits t, Theory.Endianness.(Theory.Target.endianness t = le) with
162+
| 32,false -> `ppc
163+
| 64,false -> `ppc64
164+
| 64,true -> `ppc64le
165+
| _ -> `unknown
166+
else `unknown
147167

148168
module Dis = Disasm_expert.Basic
149169

@@ -186,6 +206,7 @@ let enable_pcode_decoder () =
186206
end
187207

188208
let load ?(backend="llvm") () =
209+
register_subtargets ();
189210
enable_loader ();
190211
map_powerpc ();
191212
match backend with

oasis/powerpc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Library powerpc_plugin
1616
Path: plugins/powerpc
1717
Build$: flag(everything) || flag(powerpc)
1818
BuildDepends: bap, bap-abi, bap-c, zarith, monads, core_kernel,
19-
ppx_bap, regular, bap-api, bap-powerpc
19+
ppx_bap, regular, bap-api, bap-powerpc, bap-core-theory
2020
FindlibName: bap-plugin-powerpc
2121
InternalModules: Powerpc,
2222
Powerpc_cpu,

plugins/powerpc/powerpc_abi.ml

Lines changed: 49 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,52 @@
11
open Core_kernel[@@warning "-D"]
2+
open Bap_core_theory
23
open Bap.Std
34
open Bap_c.Std
4-
5-
include Self()
6-
7-
module Stack = C.Abi.Stack
8-
9-
type pos =
10-
| Ret_0
11-
| Ret_1
12-
| Arg of int
13-
14-
module type abi = sig
15-
val name : string
16-
val size : C.Size.base
17-
val arg : pos -> exp
18-
end
19-
20-
type abi = (module abi)
21-
22-
exception Unsupported
23-
24-
module Abi32 = struct
25-
open Powerpc.Std
26-
open PowerPC_32
27-
28-
let reg i = Int.Map.find_exn gpri i |> Bil.var
29-
let name = "ppc32"
30-
let size = object
31-
inherit C.Size.base `ILP32
32-
end
33-
let arg = function
34-
| Ret_0 -> reg 3
35-
| Ret_1 -> reg 4
36-
| Arg n -> reg (n + 3)
37-
end
38-
39-
let supported_api (module Abi : abi) {C.Type.Proto.return; args} =
40-
let word = Arch.addr_size (`ppc :> arch) |> Size.in_bits in
41-
let return = match Abi.size#bits return with
42-
| None -> None
43-
| Some width -> match Size.of_int_opt width with
44-
| None ->
45-
warning "size of return object doesn't fit into word sizes";
46-
raise Unsupported
47-
| Some sz ->
48-
let data = C.Abi.data Abi.size return in
49-
if width > word && width <= word * 2
50-
then Some (data, Bil.(Abi.arg Ret_0 ^ Abi.arg Ret_1))
51-
else if width <= word
52-
then Some (data, Abi.arg Ret_0)
53-
else
54-
(warning "size of return object doesn't fit into double word\n";
55-
raise Unsupported) in
56-
let params = List.mapi args ~f:(fun i (n,t) ->
57-
match Abi.size#bits t with
58-
| None ->
59-
warning "size of %a parameter is unknown" C.Type.pp t;
60-
raise Unsupported
61-
| Some size -> match Size.of_int_opt size with
62-
| Some sz when size <= word ->
63-
C.Abi.data Abi.size t, Abi.arg (Arg i)
64-
| _ ->
65-
warning "argument %d doesn't fit into word" i;
66-
raise Unsupported) in
67-
C.Abi.{return; params; hidden=[]}
68-
69-
let api abi proto =
70-
try Some (supported_api abi proto) with Unsupported ->
71-
warning "skipped function due to unsupported abi";
72-
None
73-
74-
let dispatch abi sub attrs proto = api abi proto
75-
76-
let main proj = match Project.arch proj with
77-
| `ppc ->
78-
info "using powerpc ABI";
79-
let abi = C.Abi.{
80-
insert_args = dispatch (module Abi32);
81-
apply_attrs = fun _ -> Fn.id
82-
} in
83-
C.Abi.register Abi32.name abi;
84-
let api = C.Abi.create_api_processor Abi32.size abi in
85-
Bap_api.process api;
86-
Project.set proj Bap_abi.name Abi32.name
87-
| _ -> proj
88-
89-
let setup () = Bap_abi.register_pass main
5+
module Arg = C.Abi.Arg
6+
open Arg.Language
7+
8+
let arena t name ~from len =
9+
Arg.Arena.create @@
10+
List.init len ~f:(fun i ->
11+
let name = sprintf "%s%d" name (from+i) in
12+
match Theory.Target.var t name with
13+
| Some v -> v
14+
| None -> failwithf "Target %s doesn't have a register named %s"
15+
(Theory.Target.to_string t) name ())
16+
17+
18+
let sysv32 t =
19+
let rev = Theory.Endianness.(equal le) (Theory.Target.endianness t) in
20+
install t (new C.Size.base `ILP32) @@ fun declare ->
21+
let* iargs = arena t ~from:3 "R" 8 in
22+
let* fargs = arena t ~from:1 "F" 8 in
23+
let* irets = Arg.Arena.irets t in
24+
let* frets = Arg.Arena.frets t in
25+
let return ~alignment:_ _ = select [
26+
C.Type.is_floating, Arg.registers ~rev frets;
27+
otherwise, choose [
28+
Arg.registers ~rev irets;
29+
Arg.reference iargs;
30+
]
31+
] in
32+
declare ~return @@ fun ~alignment:_ size -> select [
33+
C.Type.is_floating, choose [
34+
Arg.register fargs;
35+
Arg.memory;
36+
];
37+
is (size > 32), choose [
38+
Arg.pointer iargs;
39+
Arg.memory;
40+
];
41+
otherwise, choose [
42+
Arg.pointer iargs;
43+
Arg.memory;
44+
]
45+
]
46+
47+
48+
let setup () =
49+
Theory.Target.family Bap_powerpc_target.parent |>
50+
List.iter ~f:(fun t ->
51+
if Theory.Target.bits t = 32 &&
52+
Theory.Abi.(Theory.Target.abi t = gnu) then sysv32 t)

plugins/primus_lisp/site-lisp/libc-init.lisp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262

6363
(defun init (argc argv ubpev auxvec fini stinfo stack_on_entry)
6464
(declare (external "__libc_start_main")
65-
(context (abi "ppc32")))
65+
(context (target "powerpc") (abi "gnu")))
6666
(set R2 (+ stack_on_entry 0x7008))
6767
(let ((argc (read-word ptr_t stack_on_entry))
6868
(argv (ptr+1 ptr_t stack_on_entry))

plugins/primus_lisp/site-lisp/types.lisp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@
6565
(defun long () (declare (context (target mips64))) (model-ilp64 'long))
6666
(defun ptr_t () (declare (context (target mips64))) (model-ilp64 'ptr))
6767

68-
(defun char () (declare (context (abi ppc32))) (model-ilp32 'char))
69-
(defun short () (declare (context (abi ppc32))) (model-ilp32 'short))
70-
(defun int () (declare (context (abi ppc32))) (model-ilp32 'int))
71-
(defun long () (declare (context (abi ppc32))) (model-ilp32 'long))
72-
(defun ptr_t () (declare (context (abi ppc32))) (model-ilp32 'ptr))
68+
(defun char () (declare (context (target powerpc) (bits 32))) (model-ilp32 'char))
69+
(defun short () (declare (context (target powerpc) (bits 32))) (model-ilp32 'short))
70+
(defun int () (declare (context (target powerpc) (bits 32))) (model-ilp32 'int))
71+
(defun long () (declare (context (target powerpc) (bits 32))) (model-ilp32 'long))
72+
(defun ptr_t () (declare (context (target powerpc) (bits 32))) (model-ilp32 'ptr))
7373

7474
(defun char () (declare (context (arch x86_64 sysv))) (model-lp64 'char))
7575
(defun short () (declare (context (arch x86_64 sysv))) (model-lp64 'short))

0 commit comments

Comments
 (0)