Skip to content

Commit 133dd23

Browse files
bmourad01bmourad01
andauthored
Allows libraries to be allocated at non-conflicting address spaces (#1559)
* Fix not propagating term attrs in `mangle_names` during lifting * Fix style * Update testsuite revision * Log linking of lisp definitions * Emit relocations for data symbols in LLVM * KB interface for image loaders * KB-ify the LLVM loader and prefer existing bias for the unit * Add deps for `bap_llvm` library * Add bitvec dep for `bap-std` * Allocate libraries automatically We will just round up to the nearest page after the previous binary. Note that the main executable can go wherever it wants. * Log the mangling of names in `stub-resolver` * Load and map library segments in the Primus loader + apply relocations * Ignore empty filename * Rename and also log the steps of the Primus loader * Adds `relative-relocation` to the schema * Fix style * Mark `llvm:relative-relocation` only when a symbol is unavailable * Remove unused headers * Fix for LLVM >= 12 Co-authored-by: bmourad01 <[email protected]>
1 parent 1077911 commit 133dd23

File tree

14 files changed

+286
-50
lines changed

14 files changed

+286
-50
lines changed

lib/bap/bap.mli

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5738,18 +5738,35 @@ module Std : sig
57385738
- [Error err] - a file was corrupted, according to the loader.
57395739
*)
57405740
module type Loader = sig
5741-
57425741
(** [from_file name] loads a file with the given [name]. *)
57435742
val from_file : string -> Ogre.doc option Or_error.t
57445743

57455744
(** [from_data data] loads image from the specified array of bytes. *)
57465745
val from_data : Bigstring.t -> Ogre.doc option Or_error.t
5747-
57485746
end
57495747

57505748
(** [register_loader ~name backend] registers new loader. *)
57515749
val register_loader : name:string -> (module Loader) -> unit
57525750

5751+
(** Interfaces for working with the Knowledge Base.
5752+
5753+
@since 2.6.0
5754+
*)
5755+
module KB : sig
5756+
(** Same as [Loader], but parameterized with the Knowledge monad. *)
5757+
module type Loader = sig
5758+
(** [from_file name] loads a file with the given [name]. *)
5759+
val from_file : string -> Ogre.doc option knowledge
5760+
5761+
(** [from_data data] loads image from the specified array of bytes. *)
5762+
val from_data : Bigstring.t -> Ogre.doc option knowledge
5763+
end
5764+
5765+
(** [register_loader ~name backend] registers a new loader that is
5766+
parameterized with the Knowledge monad. *)
5767+
val register_loader : name:string -> (module Loader) -> unit
5768+
end
5769+
57535770
(** [find_loader name] lookups the loader registered under the
57545771
given [name].
57555772
@@ -5946,6 +5963,13 @@ module Std : sig
59465963
val relocation :
59475964
(int64 * addr, (addr -> addr -> 'a) -> 'a) Ogre.attribute
59485965

5966+
(** [relative_relocation fixup] a value referenced at the code has
5967+
address [fixup] and refers to a pointer [p], which is relocated
5968+
to [p + base_address]. *)
5969+
val relative_relocation :
5970+
(addr, (addr -> 'a) -> 'a) Ogre.attribute
5971+
5972+
59495973
(** [external_reference addr name] a piece of code at the
59505974
specified address [addr] references an external symbol with
59515975
the given [name]. *)

lib/bap/bap_project.ml

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,47 @@ module Input = struct
267267
if Set.mem mems x then (xs, mems)
268268
else (x :: xs, Set.add mems x))
269269

270+
let provide_bias = Toplevel.var "provide-bias"
271+
let provide_bias file = function
272+
| None -> Ok ()
273+
| Some bias -> try
274+
let open KB.Syntax in
275+
let bias = Word.to_bitvec bias in
276+
Toplevel.put provide_bias begin
277+
Theory.Unit.for_file file >>= fun unit ->
278+
KB.collect Theory.Unit.bias unit >>= function
279+
| Some _ -> !!()
280+
| None ->
281+
info "providing bias %a to unit %s" Bitvec.pp bias file;
282+
KB.provide Theory.Unit.bias unit @@ Some bias
283+
end;
284+
Ok (Toplevel.get provide_bias)
285+
with Toplevel.Conflict c ->
286+
Or_error.errorf "%s: %s" file @@ KB.Conflict.to_string c
287+
288+
let page_align_up x =
289+
let width = Addr.bitwidth x in
290+
let align = Word.of_int ~width 0xFFF in
291+
Addr.((x + align) land lnot align)
292+
293+
let next_bias ?bias img =
294+
let memmap = Image.memory img in
295+
match Memmap.(min_addr memmap, max_addr memmap) with
296+
| None, _ | _, None -> bias
297+
| Some lo, Some hi ->
298+
Option.value_map bias ~default:hi ~f:(fun bias ->
299+
let size = Addr.((hi - lo) ++ 1) in
300+
Addr.(bias + size)) |>
301+
page_align_up |> Option.some
302+
270303
let of_image ?target ?loader ?(libraries = []) main =
271-
List.map (main :: dedup libraries) ~f:(fun filename ->
272-
Image.create ?backend:loader filename >>| fun (img,warns) ->
304+
let rec aux ?bias acc = function
305+
| [] -> Ok (List.rev acc)
306+
| filename :: rest ->
307+
provide_bias filename bias >>= fun () ->
308+
Image.create ?backend:loader filename >>= fun (img,warns) ->
273309
List.iter warns ~f:(fun e -> warning "%a" Error.pp e);
310+
let bias = next_bias img ?bias in
274311
let spec = Image.spec img in
275312
Signal.send Info.got_img img;
276313
let finish proj = {
@@ -283,8 +320,9 @@ module Input = struct
283320
Term.set_attr sub Sub.entry_point ()
284321
| _ -> sub)
285322
} in
286-
result_of_image ?target finish filename img) |>
287-
Or_error.all
323+
let res = result_of_image ?target finish filename img in
324+
aux (res :: acc) rest ?bias in
325+
aux [] @@ dedup (main :: libraries)
288326

289327
let from_image ?target ?loader ?(libraries = []) main () =
290328
of_image ?target ?loader main ~libraries |> ok_exn

lib/bap_image/bap_image.ml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
open Core_kernel[@@warning "-D"]
2+
open Bap_knowledge
23
open Bap_core_theory
34
open Regular.Std
45
open Bap_types.Std
@@ -22,6 +23,29 @@ type loader = (module Loader)
2223
let backends : loader String.Table.t =
2324
String.Table.create ()
2425

26+
module KB = struct
27+
module type Loader = sig
28+
val from_file : string -> doc option knowledge
29+
val from_data : Bigstring.t -> doc option knowledge
30+
end
31+
32+
let register_loader ~name (module Loader : Loader) =
33+
let module Loader = struct
34+
let result = Toplevel.var "load"
35+
let from_file filename = try
36+
Toplevel.put result @@ Loader.from_file filename;
37+
Ok (Toplevel.get result)
38+
with Toplevel.Conflict c ->
39+
Or_error.errorf "%s" @@ KB.Conflict.to_string c
40+
let from_data data = try
41+
Toplevel.put result @@ Loader.from_data data;
42+
Ok (Toplevel.get result)
43+
with Toplevel.Conflict c ->
44+
Or_error.errorf "%s" @@ KB.Conflict.to_string c
45+
end in
46+
Hashtbl.add_exn backends ~key:name ~data:(module Loader)
47+
end
48+
2549
type location = {
2650
addr : addr;
2751
size : int;
@@ -147,6 +171,8 @@ module Scheme = struct
147171

148172
let relocation () =
149173
declare "relocation" (scheme fixup $ addr) Tuple.T2.create
174+
let relative_relocation () =
175+
declare "relative-relocation" (scheme fixup) Fn.id
150176
let external_reference () =
151177
declare "external-reference" (scheme addr $ name) Tuple.T2.create
152178
let base_address () = declare "base-address" (scheme addr) Fn.id
@@ -683,7 +709,6 @@ let get_loader = function
683709
let from_data = fail
684710
end)
685711

686-
687712
let invoke load data arg = match load arg with
688713
| Ok (Some doc) -> from_spec (data arg) doc
689714
| Ok None ->

lib/bap_image/bap_image.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ val register_loader : name:string -> (module Loader) -> unit
8181
val find_loader : string -> (module Loader) option
8282
val available_backends : unit -> string list
8383

84+
module KB : sig
85+
module type Loader = sig
86+
val from_file : string -> Ogre.doc option KB.t
87+
val from_data : Bigstring.t -> Ogre.doc option KB.t
88+
end
89+
90+
val register_loader : name:string -> (module Loader) -> unit
91+
end
8492

8593
module Scheme : sig
8694
open Ogre.Type
@@ -132,6 +140,9 @@ module Scheme : sig
132140
val relocation :
133141
(addr * addr, (addr -> addr -> 'a) -> 'a) Ogre.attribute
134142

143+
val relative_relocation :
144+
(addr, (addr -> 'a) -> 'a) Ogre.attribute
145+
135146
val external_reference :
136147
(addr * string, (addr -> string -> 'a) -> 'a) Ogre.attribute
137148

lib/bap_llvm/bap_llvm_loader.ml

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
open Core_kernel[@@warning "-D"]
2+
open Bap_knowledge
3+
open Bap_core_theory
24
open Bap.Std
35
open Monads.Std
46
open Or_error
57

8+
include Self()
9+
610
module Sys = Caml.Sys
711
module Unix = Caml_unix
812

13+
module Ogre = struct
14+
include Ogre
15+
include Ogre.Make(KB)
16+
end
17+
18+
919
module Primitive = struct
1020
(** [bap_llvm_load data pdb_path] analyzes [data] and builds an llvm
1121
specification of the discovered meta-data.
@@ -46,6 +56,9 @@ module LLVM = struct
4656
let relocation () =
4757
Ogre.declare ~name:"llvm:relocation" (scheme at $ addr) Tuple.T2.create
4858

59+
let relative_relocation () =
60+
Ogre.declare ~name:"llvm:relative-relocation" (scheme at) Fn.id
61+
4962
(** an external symbols with the given name is referenced ad *)
5063
let name_reference () =
5164
Ogre.declare ~name:"llvm:name-reference" (scheme at $ name) Tuple.T2.create
@@ -129,17 +142,33 @@ let iter_rows fieldname f =
129142
let provide_if cond code =
130143
if cond then code else []
131144

132-
let provide_base_and_bias new_base =
145+
let unit_bias file =
146+
let open KB.Syntax in
147+
match file with
148+
| None | Some "" -> !!None
149+
| Some file ->
150+
Theory.Unit.for_file file >>=
151+
KB.collect Theory.Unit.bias >>|
152+
Option.map ~f:Bitvec.to_int64
153+
154+
let provide_base_and_bias ?file new_base =
133155
Ogre.require LLVM.base_address >>= fun real ->
134-
Ogre.sequence @@ match new_base with
135-
| None -> [
136-
Ogre.provide bias 0L;
137-
Ogre.provide base_address real;
138-
]
139-
| Some base -> [
140-
Ogre.provide bias Int64.(base - real);
141-
Ogre.provide base_address base;
156+
Ogre.lift (unit_bias file) >>= function
157+
| Some b ->
158+
info "using provided bias 0x%Lx for file %s" b @@ Option.value_exn file;
159+
Ogre.sequence [
160+
Ogre.provide bias b;
161+
Ogre.provide base_address Int64.(real + b)
142162
]
163+
| None -> Ogre.sequence @@ match new_base with
164+
| None -> [
165+
Ogre.provide bias 0L;
166+
Ogre.provide base_address real;
167+
]
168+
| Some base -> [
169+
Ogre.provide bias Int64.(base - real);
170+
Ogre.provide base_address base;
171+
]
143172

144173
let provide_entry =
145174
Ogre.require bias >>= fun bias ->
@@ -172,6 +201,11 @@ let provide_relocations =
172201
Ogre.provide relocation Int64.(addr + bias) Int64.(dest + bias)
173202
]
174203

204+
let provide_relative_relocations =
205+
iter_rows LLVM.relative_relocation @@ fun bias addr -> [
206+
Ogre.provide relative_relocation Int64.(addr + bias)
207+
]
208+
175209
let provide_name_references =
176210
iter_rows LLVM.name_reference @@ fun bias (addr, name) -> [
177211
Ogre.provide external_reference Int64.(addr + bias) name
@@ -377,9 +411,9 @@ let provide_elf_segmentation_and_libraries data =
377411
provide_elf_segmentation @ [ElfDyn.libraries data;]
378412

379413
(** translates llvm-specific specification into the image specification *)
380-
let translate data user_base =
414+
let translate ?file data user_base =
381415
Ogre.sequence [
382-
provide_base_and_bias user_base;
416+
provide_base_and_bias user_base ?file;
383417
provide_entry;
384418
Ogre.sequence [
385419
overload "elf" @@ provide_elf_segmentation_and_libraries data;
@@ -388,6 +422,7 @@ let translate data user_base =
388422
];
389423
provide_symbols;
390424
provide_relocations;
425+
provide_relative_relocations;
391426
provide_name_references;
392427
]
393428

@@ -400,10 +435,20 @@ let pdb_path ~pdb filename =
400435
else pdb
401436
else ""
402437

403-
let translate_to_image_spec data base doc =
404-
match Ogre.exec (translate data base) doc with
405-
| Ok doc -> Ok (Some doc)
406-
| Error er -> Error er
438+
type KB.conflict += Loader_error of Error.t
439+
440+
let () = KB.Conflict.register_printer @@ function
441+
| Loader_error err ->
442+
Some (Format.asprintf "llvm loader error: %a" Error.pp err)
443+
| _ -> None
444+
445+
let liftr = function
446+
| Ok x -> KB.return x
447+
| Error x -> KB.fail @@ Loader_error x
448+
449+
let translate_to_image_spec data base doc file =
450+
let open KB.Syntax in
451+
Ogre.exec (translate data base ~file) doc >>= liftr
407452

408453
let load_doc ~pdb filename data =
409454
try Ok (Primitive.llvm_load data (pdb_path ~pdb filename))
@@ -413,10 +458,10 @@ let load_doc ~pdb filename data =
413458
| n -> Or_error.errorf "fail with unexpected error code %d" n
414459

415460
let from_data ~base ~pdb filename data =
416-
let open Or_error.Monad_infix in
417-
load_doc ~pdb filename data >>=
418-
Ogre.Doc.from_string >>=
419-
translate_to_image_spec data base
461+
let open KB.Syntax in
462+
liftr (load_doc ~pdb filename data) >>= fun s ->
463+
liftr (Ogre.Doc.from_string s) >>= fun doc ->
464+
translate_to_image_spec data base doc filename >>| Option.some
420465

421466
let map_file path =
422467
let fd = Unix.(openfile path [O_RDONLY] 0o400) in
@@ -433,10 +478,11 @@ let map_file path =
433478
[@@warning "-D"]
434479

435480
let from_file ~base ~pdb path =
436-
Or_error.(map_file path >>= from_data ~base ~pdb path)
481+
let open KB.Syntax in
482+
liftr (map_file path) >>= from_data ~base ~pdb path
437483

438484
let init ?base ?(pdb_path=Sys.getcwd ()) () =
439-
Image.register_loader ~name:"llvm" (module struct
485+
Image.KB.register_loader ~name:"llvm" (module struct
440486
let from_file = from_file ~base ~pdb:pdb_path
441487
let from_data = from_data ~base ~pdb:pdb_path ""
442488
end);

lib/bap_llvm/llvm_elf_loader.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,20 +232,29 @@ void emit_symbol_entries(const ELFObjectFile<T> &obj, ogre_doc &s) {
232232

233233
template <typename T>
234234
void emit_relocations(const ELFObjectFile<T> &obj, ogre_doc &s) {
235+
#if LLVM_VERSION_MAJOR >= 12
236+
auto rel_reloc = obj.getELFFile().getRelativeRelocationType();
237+
#else
238+
auto rel_reloc = obj.getELFFile()->getRelativeRelocationType();
239+
#endif
235240
for (auto sec : obj.sections()) {
236241
for (auto rel : sec.relocations()) {
237242
auto sym = rel.getSymbol();
243+
uint64_t raddr = prim::relocation_offset(rel);
238244
if (sym != prim::end_symbols(obj)) {
239245
auto typ = prim::symbol_type(*sym);
240246
if (typ && (*typ == SymbolRef::ST_Function ||
247+
*typ == SymbolRef::ST_Data ||
241248
*typ == SymbolRef::ST_Unknown)) {
242-
uint64_t raddr = prim::relocation_offset(rel);
243249
if (auto addr = prim::symbol_address(*sym))
244250
if (*addr) s.entry("llvm:relocation") << raddr << *addr;
245251
if (auto name = prim::symbol_name(*sym))
246252
if (!name->empty())
247253
s.entry("llvm:name-reference") << raddr << *name;
248254
}
255+
} else {
256+
auto typ = prim::relocation_type(rel);
257+
if (typ == rel_reloc) s.entry("llvm:relative-relocation") << raddr;
249258
}
250259
}
251260
}

lib/bap_llvm/llvm_loader.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static std::string scheme =
2727
"(declare llvm:elf-program-header (name str) (off int) (size int))\n"
2828
"(declare llvm:name-reference (at int) (name str))\n"
2929
"(declare llvm:relocation (at int) (addr int))\n"
30+
"(declare llvm:relative-relocation (at int))\n"
3031
"(declare llvm:section-entry (name str) (addr int) (size int) (off int))\n"
3132
"(declare llvm:section-flags (name str) (r bool) (w bool) (x bool))\n"
3233
"(declare llvm:segment-command-flags (name str) (r bool) (w bool) (x bool))\n"

lib/bap_llvm/llvm_primitives.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ error_or<section_iterator> symbol_section(const ObjectFile &obj, const SymbolRef
144144
}
145145

146146
uint64_t relocation_offset(const RelocationRef &rel) { return rel.getOffset(); }
147+
uint64_t relocation_type(const RelocationRef &rel) { return rel.getType(); }
147148

148149
std::vector<RelocationRef> relocations(const SectionRef &sec) {
149150
auto r = sec.relocations();

0 commit comments

Comments
 (0)