Skip to content

Commit c9980f4

Browse files
ivggitoleg
andauthored
calls radare2 directly (#1195)
* calls radare2 directly The ocaml-radare2 library is suffering from a few issues and it is easier and much more efficient to call radare2 directly. Here the list of issues that we have with ocaml-radare2 1) leaking file descriptors (they are never closed) 2) suboptimal inter-process communication (to get a 100 bytes ocaml-radare makes a hundred system calls) 3) lingering processes (partially fixed) In fact, we don't really need to keep the process open as we run radare2 once and immediately close, so it is much easier for us just to pass the command using the `-c` command line option. @XVilka, I saw your fix and it is not yet working, the output channels should be closed and exhausted for waitpid to return (or NOHANG) should be passed. Also, without NOHANG, the code that sends signals is actually unreachable. I've started fixing this and the other issues, but later decided that for us it is much easier and much-much more efficient to call radare2 directly. @gitoleg, please update the corresponding opam package and drop the dependency on ocaml-radare2. The new implementation also lacks the version check as I hope that the new implementation will not hang even with the older versions of radare2. If that is true, then it will help us with #1161. Also, please add the conf-radare2 package to the upstream repo and add it as a depenedency to the bap-radare2. Please, merge this PR after that. Fixes #1184. * replaces the `radare2` dependency with the `conf-radare2` Co-authored-by: gitoleg <[email protected]>
1 parent 53d1244 commit c9980f4

File tree

4 files changed

+32
-41
lines changed

4 files changed

+32
-41
lines changed

oasis/radare2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Library radare2_plugin
99
CompiledObject: best
1010
BuildDepends: bap, re.pcre, regular, bap-core-theory,
1111
bap-future, core_kernel, bap-knowledge,
12-
zarith, bitvec, radare2, yojson
12+
zarith, bitvec, yojson
1313
InternalModules: Radare2_main
1414
XMETADescription: use radare2 to provide a symbolizer
1515
XMETAExtraLines: tags="symbolizer, radare2"

opam/opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ depends: [
3333
"bap-signatures"
3434
"result"
3535
"z3"
36-
"radare2"
36+
"conf-radare2"
3737
"yojson"
3838
"result" {= "1.4"}
3939
]

plugins/radare2/.merlin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
PKG bap
2-
PKG radare2
2+
PKG yojson
33
B ../../_build/plugins/radare2
44
REC

plugins/radare2/radare2_main.ml

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,57 +28,48 @@ let provide_roots file funcs =
2828
promise_property Theory.Label.is_valid;
2929
promise_property Theory.Label.is_subroutine
3030

31-
module Field = struct
32-
(* unfortunately, we can't use Yojson.*.Utils because they are
33-
undefined for the Yojson type *)
34-
35-
let member name = function
36-
| `Assoc xs -> List.Assoc.find xs ~equal:String.equal name
37-
| _ -> invalid_arg "expects and assoc list"
38-
39-
let string = function
40-
| `String x -> x
41-
| x -> invalid_argf "expects a string got %s"
42-
(Yojson.to_string x) ()
43-
44-
let number = function
45-
| `Int i -> Z.of_int i
46-
| `Intlit s -> Z.of_string s
47-
| s -> invalid_argf "expected an address got %s"
48-
(Yojson.to_string s) ()
49-
50-
let field name parse obj = match member name obj with
51-
| None -> invalid_argf "expected member %S in the object %s"
52-
name (Yojson.to_string obj) ()
53-
| Some field -> parse field
54-
55-
let addr = field "vaddr" number
56-
let name = field "name" string
57-
let kind = field "type" string
58-
end
59-
6031
let strip str =
6132
if String.is_prefix ~prefix:"func." str then None
6233
else Option.some @@ match String.chop_prefix str ~prefix:"imp." with
6334
| Some str -> str
6435
| None -> str
6536

37+
let to_zarith = function
38+
| `Int i -> Z.of_int i
39+
| `Intlit s -> Z.of_string s
40+
| s -> invalid_argf "expected an address got %s"
41+
(Yojson.Safe.to_string s) ()
42+
43+
let parse =
44+
let open Yojson.Safe.Util in
45+
convert_each @@ fun x ->
46+
to_string @@ member "name" x,
47+
to_zarith @@ member "vaddr" x,
48+
to_string @@ member "type" x
49+
50+
let extract_symbols file =
51+
let cmd = sprintf "radare2 %s -2 -q -cisj" file in
52+
let input = Unix.open_process_in cmd in
53+
let out = parse@@Yojson.Safe.from_channel input in
54+
match Unix.close_process_in input with
55+
| Unix.WEXITED 0 -> out
56+
| WEXITED n ->
57+
warning "radare2 failed with the exit code %d" n;
58+
out
59+
| WSIGNALED _ | WSTOPPED _ ->
60+
warning "radare2 was interrupted with a signal";
61+
out
62+
6663
let provide_radare2 file =
6764
let funcs = Hashtbl.create (module struct
6865
type t = Z.t
6966
let compare = Z.compare and hash = Z.hash
7067
let sexp_of_t x = Sexp.Atom (Z.to_string x)
7168
end) in
7269
let accept name addr = Hashtbl.set funcs addr name in
73-
let symbols = match R2.with_command_j "isj" file with
74-
| `List list -> Some list
75-
| s -> warning "unexpected radare2 output: %a" Yojson.pp s; None
76-
| exception Invalid_argument msg ->
77-
warning "failed to get symbols: %s" msg; None in
78-
Option.iter symbols ~f:(List.iter ~f:(fun s ->
79-
match Field.name s, Field.addr s, Field.kind s with
80-
| name,addr, "FUNC" -> accept (strip name) addr
81-
| _ -> debug "skipping json item %a" Yojson.pp s));
70+
List.iter (extract_symbols file) ~f:(function
71+
| (name,addr,"FUNC") -> accept (strip name) addr
72+
| _ -> ());
8273
if Hashtbl.length funcs = 0
8374
then warning "failed to obtain symbols";
8475
let symbolizer = Symbolizer.create @@ fun addr ->

0 commit comments

Comments
 (0)