Skip to content

Commit f995d28

Browse files
authored
allows bypassing checks when storing memory, uses it for relocations (#1567)
When we perform relocations on object files, we do the linker work not the loader, therefore we do not need to check if the memory is writable or even loadable. The easiest option is to extend the Primus memory interface with primitives that perform writing without any checks.
1 parent 79fd1a2 commit f995d28

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

lib/bap_primus/bap_primus.mli

+31-3
Original file line numberDiff line numberDiff line change
@@ -2573,7 +2573,7 @@ module Std : sig
25732573
val get : addr -> value Machine.t
25742574

25752575

2576-
(** [set a x] stores the byte [x] at the address [a].
2576+
(** [set a x] stores [x] at the address [a].
25772577
25782578
raises the [Pagefault] machine exception if [a] is not mapped,
25792579
or not writable.
@@ -2584,6 +2584,19 @@ module Std : sig
25842584
val set : addr -> value -> unit Machine.t
25852585

25862586

2587+
(** [set_never_fail a x] stores [x] at [a] bypassing any
2588+
checks.
2589+
2590+
Forcefully stores [x] at the address [a] without any
2591+
sanity checks, i.e., doesn't check if the memory is mapped or
2592+
is it writable.
2593+
2594+
Precondition: the size of the address and the size of the
2595+
datum match with the current [memory] sizes.
2596+
2597+
@since 2.6.0 *)
2598+
val set_never_fail : addr -> value -> unit Machine.t
2599+
25872600
(** [del p] removes the value associated with the pointer [p]. *)
25882601
val del : addr -> unit Machine.t
25892602

@@ -2597,10 +2610,25 @@ module Std : sig
25972610
25982611
Same as [Value.of_word x >>= set a].
25992612
2600-
Precondition: [Value.bitwidth x = 8].
2601-
*)
2613+
Precondition: the size of the address and the size of the
2614+
datum match with the current [memory] sizes. *)
26022615
val store : addr -> word -> unit Machine.t
26032616

2617+
(** [store_never_fail a x] stores [x] at [a] bypassing any
2618+
checks.
2619+
2620+
Forcefully stores [x] at the address [a] without any
2621+
sanity checks, i.e., doesn't check if the memory is mapped or
2622+
is it writable.
2623+
2624+
Same as [Value.of_word x >>= set_never_fail a].
2625+
2626+
Precondition: the size of the address and the size of the
2627+
datum match with the current [memory] sizes.
2628+
2629+
@since 2.6.0 *)
2630+
val store_never_fail : addr -> word -> unit Machine.t
2631+
26042632
(** [add_text mem] maps a memory chunk [mem] as executable and
26052633
readonly segment of machine memory.*)
26062634
val add_text : mem -> unit Machine.t

lib/bap_primus/bap_primus_memory.ml

+11-3
Original file line numberDiff line numberDiff line change
@@ -271,19 +271,19 @@ module Make(Machine : Machine) = struct
271271
Generate.word g (Generator.width g) >>=
272272
remembered {values; layers} addr
273273

274-
let set_value s addr value = {
274+
let set_value addr value s = {
275275
s with
276276
values = Map.set s.values ~key:addr ~data:value
277277
}
278278

279279
let write addr value s =
280280
if Map.mem s.values addr
281-
then Machine.return @@ set_value s addr value
281+
then Machine.return @@ set_value addr value s
282282
else match find_layer addr s.layers with
283283
| None -> pagefault addr
284284
| Some {perms={readonly=true}} -> pagefault addr
285285
| Some _ ->
286-
Machine.return @@ set_value s addr value
286+
Machine.return @@ set_value addr value s
287287

288288
let add_layer layer t = {t with layers = layer :: t.layers}
289289
let (++) = add_layer
@@ -336,12 +336,20 @@ module Make(Machine : Machine) = struct
336336
write addr value >>=
337337
put_curr
338338

339+
let set_never_fail addr value =
340+
get_curr >>|
341+
set_value addr value >>=
342+
put_curr
343+
344+
339345
let del addr = update @@ fun s -> {
340346
s with values = Map.remove s.values addr
341347
}
342348

343349
let load addr = get addr >>| Value.to_word
344350
let store addr value = Value.of_word value >>= set addr
351+
let store_never_fail addr value =
352+
Value.of_word value >>= set_never_fail addr
345353

346354
let is_mapped addr =
347355
get_curr >>| is_mapped addr

lib/bap_primus/bap_primus_memory.mli

+3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ module Make(Machine : Machine) : sig
2626

2727
val load : addr -> word Machine.t
2828
val store : addr -> word -> unit Machine.t
29+
val store_never_fail : addr -> word -> unit Machine.t
2930

3031
val get : addr -> value Machine.t
3132
val set : addr -> value -> unit Machine.t
33+
val set_never_fail : addr -> value -> unit Machine.t
34+
3235
val del : addr -> unit Machine.t
3336

3437
val add_text : mem -> unit Machine.t

plugins/primus_loader/primus_loader_basic.ml

+13-11
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@ module Make(Param : Param)(Machine : Primus.Machine.S) = struct
133133
Project.libraries proj |> List.map ~f:Project.Library.memory |>
134134
Machine.List.fold ~init ~f:(fun init m -> one_memmap m ~init)
135135

136-
let save_word endian word ptr =
136+
let save_word ?(force=false) endian word ptr =
137+
let store = if force then Mem.store_never_fail else Mem.store in
137138
Word.enum_bytes word endian |>
138139
Machine.Seq.fold ~init:ptr ~f:(fun ptr byte ->
139-
Mem.store ptr byte >>| fun () ->
140+
store ptr byte >>| fun () ->
140141
Word.succ ptr)
141142

142143
let read_word endian ptr =
@@ -176,8 +177,9 @@ module Make(Param : Param)(Machine : Primus.Machine.S) = struct
176177
let fixup_one_reloc endian width (fixup, addr) =
177178
let fixup = Addr.of_int64 ~width fixup in
178179
let addr = Word.of_int64 ~width addr in
179-
info "writing %a for relocation %a" Word.pp addr Addr.pp fixup;
180-
save_word endian addr fixup >>| ignore
180+
debug "writing %a for relocation %a" Word.pp addr Addr.pp fixup;
181+
Machine.ignore_m @@
182+
save_word ~force:true endian addr fixup
181183

182184
let fixup_relocs_of_doc target doc =
183185
let endian = endian_of_target target in
@@ -279,21 +281,21 @@ module Make(Param : Param)(Machine : Primus.Machine.S) = struct
279281
Machine.Seq.iter ~f:(fun (name,addr) -> set_word name addr)
280282

281283
let init () =
282-
info "setting up stack";
284+
debug "setting up stack";
283285
setup_stack () >>= fun () ->
284-
info "setting up main frame";
286+
debug "setting up main frame";
285287
setup_main_frame () >>= fun () ->
286-
info "loading segments";
288+
debug "loading segments";
287289
load_segments () >>= fun e1 ->
288-
info "mapping segments";
290+
debug "mapping segments";
289291
map_segments () >>= fun e2 ->
290-
info "fixing up relocations";
292+
debug "fixing up relocations";
291293
fixup_relocs () >>= fun () ->
292-
info "setting up registers";
294+
debug "setting up registers";
293295
let endp = Addr.max e1 e2 in
294296
set_word "posix:endp" endp >>= fun () ->
295297
set_word "posix:brk" endp >>= fun () ->
296298
setup_registers () >>= fun () ->
297-
info "initializing names";
299+
debug "initializing names";
298300
init_names ()
299301
end

0 commit comments

Comments
 (0)