You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.8 KiB
179 lines
4.8 KiB
/*
|
|
* vim: set ft=rust:
|
|
* vim: set ft=reason:
|
|
*
|
|
* Copyright (c) 2009 - 2013 Monoidics ltd.
|
|
* Copyright (c) 2013 - present Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
open! IStd;
|
|
|
|
|
|
/** The Smallfoot Intermediate Language: Decompiled Expressions */
|
|
let module L = Logging;
|
|
|
|
let module F = Format;
|
|
|
|
|
|
/** expression representing the result of decompilation */
|
|
type t =
|
|
| Darray t t
|
|
| Dbinop Binop.t t t
|
|
| Dconst Const.t
|
|
| Dsizeof Typ.t (option t) Subtype.t
|
|
| Dderef t
|
|
| Dfcall t (list t) Location.t CallFlags.t
|
|
| Darrow t Ident.fieldname
|
|
| Ddot t Ident.fieldname
|
|
| Dpvar Pvar.t
|
|
| Dpvaraddr Pvar.t
|
|
| Dunop Unop.t t
|
|
| Dunknown
|
|
| Dretcall t (list t) Location.t CallFlags.t;
|
|
|
|
|
|
/** Value paths: identify an occurrence of a value in a symbolic heap
|
|
each expression represents a path, with Dpvar being the simplest one */
|
|
type vpath = option t;
|
|
|
|
let java () => !Config.curr_language == Config.Java;
|
|
|
|
let eradicate_java () => Config.eradicate && java ();
|
|
|
|
|
|
/** convert a dexp to a string */
|
|
let rec to_string =
|
|
fun
|
|
| Darray de1 de2 => to_string de1 ^ "[" ^ to_string de2 ^ "]"
|
|
| Dbinop op de1 de2 => "(" ^ to_string de1 ^ Binop.str Pp.text op ^ to_string de2 ^ ")"
|
|
| Dconst (Cfun pn) => Procname.to_simplified_string pn
|
|
| Dconst c => Const.to_string c
|
|
| Dderef de => "*" ^ to_string de
|
|
| Dfcall fun_dexp args _ {cf_virtual: isvirtual} => {
|
|
let pp_arg fmt de => F.fprintf fmt "%s" (to_string de);
|
|
let pp_args fmt des =>
|
|
if (eradicate_java ()) {
|
|
if (des != []) {
|
|
F.fprintf fmt "..."
|
|
}
|
|
} else {
|
|
Pp.comma_seq pp_arg fmt des
|
|
};
|
|
let pp_fun fmt => (
|
|
fun
|
|
| Dconst (Cfun pname) => {
|
|
let s =
|
|
switch pname {
|
|
| Procname.Java pname_java => Procname.java_get_method pname_java
|
|
| _ => Procname.to_string pname
|
|
};
|
|
F.fprintf fmt "%s" s
|
|
}
|
|
| de => F.fprintf fmt "%s" (to_string de)
|
|
);
|
|
let (receiver, args') =
|
|
switch args {
|
|
| [Dpvar pv, ...args'] when isvirtual && Pvar.is_this pv => (None, args')
|
|
| [a, ...args'] when isvirtual => (Some a, args')
|
|
| _ => (None, args)
|
|
};
|
|
let pp fmt => {
|
|
let pp_receiver fmt => (
|
|
fun
|
|
| None => ()
|
|
| Some arg => F.fprintf fmt "%a." pp_arg arg
|
|
);
|
|
F.fprintf fmt "%a%a(%a)" pp_receiver receiver pp_fun fun_dexp pp_args args'
|
|
};
|
|
F.asprintf "%t" pp
|
|
}
|
|
| Darrow (Dpvar pv) f when Pvar.is_this pv =>
|
|
/* this->fieldname */
|
|
Ident.fieldname_to_simplified_string f
|
|
| Darrow de f =>
|
|
if (Ident.fieldname_is_hidden f) {
|
|
to_string de
|
|
} else if (java ()) {
|
|
to_string de ^ "." ^ Ident.fieldname_to_flat_string f
|
|
} else {
|
|
to_string de ^ "->" ^ Ident.fieldname_to_string f
|
|
}
|
|
| Ddot (Dpvar _) fe when eradicate_java () =>
|
|
/* static field access */
|
|
Ident.fieldname_to_simplified_string fe
|
|
| Ddot de f =>
|
|
if (Ident.fieldname_is_hidden f) {
|
|
"&" ^ to_string de
|
|
} else if (java ()) {
|
|
to_string de ^ "." ^ Ident.fieldname_to_flat_string f
|
|
} else {
|
|
to_string de ^ "." ^ Ident.fieldname_to_string f
|
|
}
|
|
| Dpvar pv => Mangled.to_string (Pvar.get_name pv)
|
|
| Dpvaraddr pv => {
|
|
let s =
|
|
if (eradicate_java ()) {
|
|
Pvar.get_simplified_name pv
|
|
} else {
|
|
Mangled.to_string (Pvar.get_name pv)
|
|
};
|
|
let ampersand =
|
|
if (eradicate_java ()) {
|
|
""
|
|
} else {
|
|
"&"
|
|
};
|
|
ampersand ^ s
|
|
}
|
|
| Dunop op de => Unop.str op ^ to_string de
|
|
| Dsizeof typ _ _ => F.asprintf "%a" (Typ.pp_full Pp.text) typ
|
|
| Dunknown => "unknown"
|
|
| Dretcall de _ _ _ => "returned by " ^ to_string de;
|
|
|
|
|
|
/** Pretty print a dexp. */
|
|
let pp fmt de => F.fprintf fmt "%s" (to_string de);
|
|
|
|
|
|
/** Pretty print a value path */
|
|
let pp_vpath pe fmt vpath => {
|
|
let pp fmt =>
|
|
fun
|
|
| Some de => pp fmt de
|
|
| None => ();
|
|
if (pe.Pp.kind == Pp.HTML) {
|
|
F.fprintf
|
|
fmt
|
|
" %a{vpath: %a}%a"
|
|
Io_infer.Html.pp_start_color
|
|
Pp.Orange
|
|
pp
|
|
vpath
|
|
Io_infer.Html.pp_end_color
|
|
()
|
|
} else {
|
|
F.fprintf fmt "%a" pp vpath
|
|
}
|
|
};
|
|
|
|
let rec has_tmp_var =
|
|
fun
|
|
| Dpvar pvar
|
|
| Dpvaraddr pvar => Pvar.is_frontend_tmp pvar
|
|
| Dderef dexp
|
|
| Ddot dexp _
|
|
| Darrow dexp _
|
|
| Dunop _ dexp
|
|
| Dsizeof _ (Some dexp) _ => has_tmp_var dexp
|
|
| Darray dexp1 dexp2
|
|
| Dbinop _ dexp1 dexp2 => has_tmp_var dexp1 || has_tmp_var dexp2
|
|
| Dretcall dexp dexp_list _ _
|
|
| Dfcall dexp dexp_list _ _ => has_tmp_var dexp || IList.exists has_tmp_var dexp_list
|
|
| Dconst _
|
|
| Dunknown
|
|
| Dsizeof _ None _ => false;
|