diff --git a/lib/bap/bap.mli b/lib/bap/bap.mli index 9ef811433..9638db6cf 100644 --- a/lib/bap/bap.mli +++ b/lib/bap/bap.mli @@ -5506,10 +5506,20 @@ module Std : sig type result = (t * Error.t list) Or_error.t (** [create ?backend filename] creates an image of the file specified - specified by the [filename]. If [backend] is equal to "auto", then - all backends are tried in order. If only one backend can read this - file (i.e., there is no ambiguity), then image is returned. If - [backend] is not specified, then the LLVM backend is used. *) + by the [filename]. If [backend] is not specified, then + all availabe backends are used and their information is + merged. If the information provided by all backends agree (i.e., + there's no conflicting information), then image is returned. + If [backend] is an explicit file path, then it is read as an + OGRE file and used for loading. Otherwise, [backend] should be + a name of one of the backends registered either with + [register_backend] or [register_loader]. See + [available_backends] for the list of available backends. + + @since 2.5.0 accepts backend accepts an explicit file path, + note a file path is explicit if it exists and + [Fn.non Filename.is_implicit]. + *) val create : ?backend:string -> path -> result (** [of_string ?backend ~data] creates an image from the specified @@ -9084,7 +9094,7 @@ module Std : sig is translated to, {v #11 := #9 + 13 - #12 := 11 * #11 + #12 := 11 * #11 #10 := #12 - 17 v} @since 2.5.0 *) diff --git a/lib/bap_image/bap_image.ml b/lib/bap_image/bap_image.ml index 72b10759f..928141a56 100644 --- a/lib/bap_image/bap_image.ml +++ b/lib/bap_image/bap_image.ml @@ -664,15 +664,24 @@ let merge_loaders () : loader = let get_loader = function | None -> merge_loaders () + | Some name when Sys.file_exists name && + Fn.non Filename.is_implicit name -> + let local _ = match Ogre.Doc.from_file name with + | Error err -> Error err + | Ok doc -> Ok (Some doc) in + (module struct + let from_file = local + let from_data = local + end) | Some name -> match Hashtbl.find backends name with | Some loader -> loader | None -> - let module Failure = struct - let fail _ = Result.failf "Unknown image loader %s" name () + let fail _ = Result.failf "Unknown image loader %s" name () in + (module struct let from_file = fail let from_data = fail - end in - (module Failure) + end) + let invoke load data arg = match load arg with | Ok (Some doc) -> from_spec (data arg) doc diff --git a/plugins/disassemble/disassemble_main.ml b/plugins/disassemble/disassemble_main.ml index 4e36d5e2f..2c6a12060 100644 --- a/plugins/disassemble/disassemble_main.ml +++ b/plugins/disassemble/disassemble_main.ml @@ -243,7 +243,18 @@ let input = Extension.Command.argument let loader = Extension.Command.parameter ~doc:"Use the specified loader. - Use the loader `raw' to load unstructured files" + The loader could be either an identifier or a filename. \ + The filename has to be explicit, i.e., to start with an \ + explicit reference to the root directory or to the current \ + directory (e.g., $(b,./), or $(b,../), or $(b,/) in Unix). \ + The contents of the file should be a well-formed OGRE \ + document that contains the necessary meta-information \ + about the binary. \ + The default loader is named $(b,llvm) and uses LLVM loaders \ + to parse the input binary and supports ELF, MachO, and COFF \ + (including Windows PE), formats. \ + To load unstructured files use the $(b,raw) loader and \ + specify the loader parameters via the $(b,raw) plugin." Extension.Type.(string =? "llvm") "loader" @@ -362,13 +373,14 @@ let save_knowledge ~had_knowledge ~update digest = function | Some _ -> () - let create_and_process input outputs passes loader target update kb ctxt = + let uses_file_loader = Sys.file_exists loader && + Fn.non Filename.is_implicit loader in let package = input in let digest = make_digest [ Extension.Configuration.digest ctxt; Caml.Digest.file input; - loader; + if uses_file_loader then Caml.Digest.file loader else loader; ] in let had_knowledge = load_knowledge digest kb in let input = Project.Input.load ~target ~loader input in