Skip to content

Commit 2b789c4

Browse files
authored
improves the main subroutine discovery within glibc runtime (#1532)
1) makes it more robust by lifting an assumption that __libc_start_main is called in the first block of the start subroutine (now it could be any block); 2) uses the new bap-c functionality to properly apply abi processor on the discovered main subroutine.
1 parent c100c28 commit 2b789c4

File tree

1 file changed

+23
-61
lines changed

1 file changed

+23
-61
lines changed

plugins/glibc_runtime/glibc_runtime_main.ml

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ let find_by_name prog name =
3434
Term.enum sub_t prog |> Seq.find ~f:(fun sub -> String.equal (Sub.name sub) name)
3535

3636
let find_first_caller prog tid =
37-
Term.enum sub_t prog |> Seq.find ~f:(fun sub ->
38-
Term.enum blk_t sub |> Seq.exists ~f:(fun blk ->
37+
Term.enum sub_t prog |> Seq.find_map ~f:(fun sub ->
38+
Term.enum blk_t sub |> Seq.find ~f:(fun blk ->
3939
Term.enum jmp_t blk |> Seq.exists ~f:(fun jmp ->
4040
match Jmp.kind jmp with
4141
| Call c -> Label.equal (Call.target c) (Direct tid)
@@ -81,14 +81,12 @@ let find_libc_start_main prog =
8181
let detect_main_address prog =
8282
let open Option.Monad_infix in
8383
find_by_name prog "__libc_start_main" >>= fun start ->
84-
find_first_caller prog (Term.tid start) >>= fun caller ->
85-
Term.first blk_t caller >>= fun entry ->
84+
find_first_caller prog (Term.tid start) >>= fun entry ->
8685
Term.first arg_t start >>= fun arg ->
8786
let defs = Term.enum def_t ~rev:true entry in
8887
match Arg.rhs arg with
89-
| Bil.Var reg ->
90-
Seq.find defs ~f:(fun def ->
91-
Var.same (Def.lhs def) reg) >>| Def.rhs >>= proj_int
88+
| Bil.Var reg -> Seq.find defs ~f:(fun def ->
89+
Var.same (Def.lhs def) reg) >>| Def.rhs >>= proj_int
9290
| Bil.Load (_,addr,_,_) ->
9391
Seq.find_map defs ~f:(fun def -> match Def.rhs def with
9492
| Bil.Store (_,a,e,_,_) when Exp.equal addr a -> Some e
@@ -108,19 +106,15 @@ let rename_main abi prog =
108106
if is_sub_absent prog "main"
109107
then match detect_main_address prog with
110108
| None -> prog
111-
| Some addr -> Term.map sub_t prog ~f:(fun sub ->
112-
match Term.get_attr sub address with
113-
| Some a when Addr.equal addr a ->
114-
reinsert_args_for_new_name ~abi sub "main"
115-
| _ -> sub)
109+
| Some addr ->
110+
info "the main subroutine address is %a" Addr.pp addr;
111+
Term.map sub_t prog ~f:(fun sub ->
112+
match Term.get_attr sub address with
113+
| Some a when Addr.equal addr a ->
114+
reinsert_args_for_new_name ~abi sub "main"
115+
| _ -> sub)
116116
else prog
117117

118-
let find_abi_processor proj =
119-
let (let*) = Option.(>>=) in
120-
let* name = Project.get proj Bap_abi.name in
121-
let* proc = C.Abi.get_processor name in
122-
Some proc
123-
124118
let rename_libc_start_main prog =
125119
if is_sub_absent prog "__libc_start_main"
126120
then match find_libc_start_main prog with
@@ -134,53 +128,21 @@ let rename_libc_start_main prog =
134128
else prog
135129

136130
module Main = struct
137-
let cv = C.Type.Qualifier.{
138-
const = false;
139-
volatile = false;
140-
restrict = ();
141-
}
142-
143-
let cvr = C.Type.Qualifier.{
144-
const = false;
145-
volatile = false;
146-
restrict = false;
147-
}
148-
149-
let basic t = `Basic C.Type.Spec.{t; attrs=[]; qualifier=cv}
150-
let ptr t = `Pointer C.Type.Spec.{t; attrs=[]; qualifier=cvr}
151-
152-
let proto : C.Type.proto = C.Type.Proto.{
153-
variadic = false;
154-
return = basic `sint;
155-
args = [
156-
"argc", basic `sint;
157-
"argv", ptr (ptr (basic `char));
158-
];
159-
}
160-
161-
let var t (data : C.Data.t) name =
162-
match data with
163-
| Imm (sz,_) -> Var.create name (Type.Imm (Size.in_bits sz))
164-
| Ptr _ ->
165-
Var.create name (Type.Imm (Theory.Target.code_addr_size t))
166-
| _ -> assert false
167-
168-
let arg intent t (data,exp) name =
169-
Arg.create ~intent (var t data name) exp
131+
let proto : C.Type.proto =
132+
match C.Type.function_
133+
~return:(C.Type.basic `sint) [
134+
"argc", C.Type.basic `sint;
135+
"argv", C.Type.(pointer (pointer (basic `char)))
136+
]
137+
with `Function {t=proto} -> proto
138+
| _ -> assert false
170139

171140
let abi proj main =
172141
let t = Project.target proj in
173-
match find_abi_processor proj with
142+
match C.Abi.lookup t with
174143
| None -> main
175-
| Some {C.Abi.insert_args} ->
176-
match insert_args main [] proto with
177-
| Some {C.Abi.return=Some ret; params=[argc; argv]} ->
178-
List.fold ~init:main ~f:(Term.append arg_t)[
179-
arg In t argc "main_argc";
180-
arg Both t argv "main_argv";
181-
arg Out t ret "main_result";
182-
]
183-
| _ -> main
144+
| Some proc ->
145+
C.Abi.apply proc (C.Abi.model t) [] proto main
184146
end
185147

186148
let fix_main proj =

0 commit comments

Comments
 (0)