Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allows bypassing checks when storing memory, uses it for relocations #1567

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions lib/bap_primus/bap_primus.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2573,7 +2573,7 @@ module Std : sig
val get : addr -> value Machine.t


(** [set a x] stores the byte [x] at the address [a].
(** [set a x] stores [x] at the address [a].

raises the [Pagefault] machine exception if [a] is not mapped,
or not writable.
Expand All @@ -2584,6 +2584,19 @@ module Std : sig
val set : addr -> value -> unit Machine.t


(** [set_never_fail a x] stores [x] at [a] bypassing any
checks.

Forcefully stores [x] at the address [a] without any
sanity checks, i.e., doesn't check if the memory is mapped or
is it writable.

Precondition: the size of the address and the size of the
datum match with the current [memory] sizes.

@since 2.6.0 *)
val set_never_fail : addr -> value -> unit Machine.t

(** [del p] removes the value associated with the pointer [p]. *)
val del : addr -> unit Machine.t

Expand All @@ -2597,10 +2610,25 @@ module Std : sig

Same as [Value.of_word x >>= set a].

Precondition: [Value.bitwidth x = 8].
*)
Precondition: the size of the address and the size of the
datum match with the current [memory] sizes. *)
val store : addr -> word -> unit Machine.t

(** [store_never_fail a x] stores [x] at [a] bypassing any
checks.

Forcefully stores [x] at the address [a] without any
sanity checks, i.e., doesn't check if the memory is mapped or
is it writable.

Same as [Value.of_word x >>= set_never_fail a].

Precondition: the size of the address and the size of the
datum match with the current [memory] sizes.

@since 2.6.0 *)
val store_never_fail : addr -> word -> unit Machine.t

(** [add_text mem] maps a memory chunk [mem] as executable and
readonly segment of machine memory.*)
val add_text : mem -> unit Machine.t
Expand Down
14 changes: 11 additions & 3 deletions lib/bap_primus/bap_primus_memory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -271,19 +271,19 @@ module Make(Machine : Machine) = struct
Generate.word g (Generator.width g) >>=
remembered {values; layers} addr

let set_value s addr value = {
let set_value addr value s = {
s with
values = Map.set s.values ~key:addr ~data:value
}

let write addr value s =
if Map.mem s.values addr
then Machine.return @@ set_value s addr value
then Machine.return @@ set_value addr value s
else match find_layer addr s.layers with
| None -> pagefault addr
| Some {perms={readonly=true}} -> pagefault addr
| Some _ ->
Machine.return @@ set_value s addr value
Machine.return @@ set_value addr value s

let add_layer layer t = {t with layers = layer :: t.layers}
let (++) = add_layer
Expand Down Expand Up @@ -336,12 +336,20 @@ module Make(Machine : Machine) = struct
write addr value >>=
put_curr

let set_never_fail addr value =
get_curr >>|
set_value addr value >>=
put_curr


let del addr = update @@ fun s -> {
s with values = Map.remove s.values addr
}

let load addr = get addr >>| Value.to_word
let store addr value = Value.of_word value >>= set addr
let store_never_fail addr value =
Value.of_word value >>= set_never_fail addr

let is_mapped addr =
get_curr >>| is_mapped addr
Expand Down
3 changes: 3 additions & 0 deletions lib/bap_primus/bap_primus_memory.mli
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ module Make(Machine : Machine) : sig

val load : addr -> word Machine.t
val store : addr -> word -> unit Machine.t
val store_never_fail : addr -> word -> unit Machine.t

val get : addr -> value Machine.t
val set : addr -> value -> unit Machine.t
val set_never_fail : addr -> value -> unit Machine.t

val del : addr -> unit Machine.t

val add_text : mem -> unit Machine.t
Expand Down
24 changes: 13 additions & 11 deletions plugins/primus_loader/primus_loader_basic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ module Make(Param : Param)(Machine : Primus.Machine.S) = struct
Project.libraries proj |> List.map ~f:Project.Library.memory |>
Machine.List.fold ~init ~f:(fun init m -> one_memmap m ~init)

let save_word endian word ptr =
let save_word ?(force=false) endian word ptr =
let store = if force then Mem.store_never_fail else Mem.store in
Word.enum_bytes word endian |>
Machine.Seq.fold ~init:ptr ~f:(fun ptr byte ->
Mem.store ptr byte >>| fun () ->
store ptr byte >>| fun () ->
Word.succ ptr)

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

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

let init () =
info "setting up stack";
debug "setting up stack";
setup_stack () >>= fun () ->
info "setting up main frame";
debug "setting up main frame";
setup_main_frame () >>= fun () ->
info "loading segments";
debug "loading segments";
load_segments () >>= fun e1 ->
info "mapping segments";
debug "mapping segments";
map_segments () >>= fun e2 ->
info "fixing up relocations";
debug "fixing up relocations";
fixup_relocs () >>= fun () ->
info "setting up registers";
debug "setting up registers";
let endp = Addr.max e1 e2 in
set_word "posix:endp" endp >>= fun () ->
set_word "posix:brk" endp >>= fun () ->
setup_registers () >>= fun () ->
info "initializing names";
debug "initializing names";
init_names ()
end