123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277(**************************************************************************)(* This file is part of the Codex semantics library. *)(* *)(* Copyright (C) 2013-2025 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE). *)(* *)(**************************************************************************)(* Helper functions to parse the command line.
Note: must be called after the types and image are loaded. *)(** Parses a type from a string *)lettype_of_string=Types.Parse_ctypes.type_of_string(* Parse an address or a symbol. *)letaddress_of_strings=matchs.[0]with|'0'->Z.of_strings|_->beginmatchLoader_utils.address_of_symbol_by_name~name:s@@Kernel_functions.get_img()with|None->failwith("Unknown address `"^s^"'")|Somex->Z.of_intxend;;letdirective_of_strings=matchswith|"stop"->`stop|"nop"->`nop|"explore"->`explore|_->try(* Codex_log.feedback "Scanning |%s|" s; *)lettyp=Scanf.sscanfs"return_unknown(%s@)"type_of_stringin`return_unknown(typ)withScanf.Scan_failure_->try(* Codex_log.feedback "Scanning |%s|" s; *)letaddress=Scanf.sscanfs"skip_to(%s@)"address_of_stringin`skip_to(Virtual_address.create(Z.to_intaddress))withScanf.Scan_failure_->failwith("Unknown directive: "^s);;includeCli.Make(structletname="codex"letshortname="codex"end)moduleApplicationFile=structincludeBuilder.String(structletname="app-file"letdefault=""letdoc="Path to an application ELF"end)endmoduleTypeConfigurationFile=structincludeBuilder.String(structletname="type-file"letdefault=""letdoc="Path to the file containing the type definitions"end)endmoduleX86Types=structincludeBuilder.String(structletname="x86-types"letdefault="rr"letdoc="Version of the C types for x86 OS"end)endmoduleUseShape=structincludeBuilder.No(structletname="use-shape"letdoc="Set to not use shape"end)endmoduleNbTasks=structincludeBuilder.Integer(structletname="nb-tasks"letdoc="Number of tasks (required)"letdefault=0end)endmoduleAnalyzeKernel=structincludeBuilder.False(structletname="analyze-kernel"letdoc="Whether to analyze a kernel (tailored, more complex analysis)"end)endmoduleDynThreads=structincludeBuilder.No(structletname="dyn-threads"letdoc="Analyzed kernel features dynamic thread creation"end)end(*
module FnArgs = struct
include Builder.String_list (struct
let name = "fn-args"
let doc = "Argument types to put in the stack at the initial state"
end)
let get() = get() |> List.map type_of_string
end
*)moduleGlobalsTypes=structincludeBuilder.String_list(structletname="globals-types"letdoc="Assignment of globals to types. It is a coma-separated list of addr=typ, where address can be symbols or hexa."end)letget()=get()|>List.map(funs->letaddr,typ=matchString.split_on_char'='swith|[a;b]->String.trima,String.trimb|_->failwith("Global spec should be of the form addr=typ; got "^s)inletaddr=address_of_stringaddrinlettyp=type_of_stringtypin(addr,typ))endmoduleHooks=structincludeBuilder.String_list(structletname="hooks"letdoc="Hooks at certain addresses (which can be symbols or hexa) to directives, of the form addr=directive, where directive is stop|explore|skip. stop stops here, explore means do meet over all paths for the function from this point, and skip means immediately return (must be at function entry)"end)letget()=get()|>List.map(funs->letaddr,directive=matchString.split_on_char'='swith|[a;b]->String.trima,String.trimb|_->failwith("Global spec should be of the form addr=directive; got "^s)inletaddr=Virtual_address.create@@Z.to_int@@address_of_stringaddrinletdirective=directive_of_stringdirectivein(addr,directive))endmoduleFocusing=structincludeBuilder.No(structletname="focusing"letdoc="Activate focusing"end)endmoduleOutput_Html=structincludeBuilder.String_option(structletname="output-html"letdoc="Output the results in an html file"end)endmoduleUseLoopDomain=structincludeBuilder.False(structletname="use-loop-domain"letdoc="Activate inductive loop domain"end)endmoduleVariableDisplay=Builder.Variant_choice(structtypet=Domains.Term_domain.pretty_termsletname="variable-display"letdoc="How codex should display variable information. \
\ One of 'value' (only print inferred value, default)\
\ 'symbolic' (print associated symbolic term)\
\ 'both' (print both value and symbolic term)\
\ 'relation' (print value, symbolic term, and union-find relation associated with this term)."openDomains.Term_domainletto_string=function|Value->"value"|Both->"both"|Symbolic->"symbolic"|Relation->"relation"letof_string=function|"value"->Value|"both"->Both|"symbolic"->Symbolic|"relation"->Relation|_->assertfalseletchoices=["value";"both";"symbolic";"relation"]letdefault=Valueend)moduleMMIOs=structincludeBuilder.String_list(structletname="mmios"letdoc="sets memory blocks of the form addr+size as readable but unknown content"end)letget()=get()|>List.map(funs->letaddr,size=matchString.split_on_char'+'swith|[a;b]->String.trima,String.trimb|_->failwith("Global spec should be of the form addr+size; got "^s)inletsize=int_of_stringsizeinletaddr=int_of_stringaddrin(addr,size))end(*
module GlobalSymbols = struct
include Builder.String_list (struct
let name = "global-symbols"
let doc = "Declaration of global symbols and their types. It is a coma-separated list of sym=typ, where symbols are identifiers"
end)
let get() = get() |> List.map (fun s ->
let symb,typ = match String.split_on_char '=' s with
| [a;b] -> String.trim a,String.trim b
| _ -> failwith ("Global spec should be of the form symb=typ; got " ^ s)
in
let typ = type_of_string typ in
(symb,typ)
)
end
*)moduleLocation=struct(* Absolute location representing an address. *)typeaddress_location=int64Syntax_tree.Location_identifier.tmoduleL=structinclude(Tracelog:sigtypelocation=Tracelog.location=..end)typelocation+=|Functionofstring|Instructionof{locid:address_location;address:int64}|Dba_instrof{locid:Dba.Instr.tSyntax_tree.Location_identifier.t;dba_instr:Dba.Instr.t}(* Instr and position in the dhunk. *)|Dba_exprof{locid:Dba.Expr.tSyntax_tree.Location_identifier.t;dba_expr:Dba.Expr.t}(* Expr and position in the expr. *)typet=locationendincludeLletpp_locfmtlocation=matchlocationwith|Functionf->Format.fprintffmt"In function `%s':@ "f|Instruction{address}->Format.fprintffmt"In function `%08Lx':@ "address|Dba_instr{dba_instr}->Format.fprintffmt"In Dba_instr `%s':@ "(dba_instr|>Binsec2syntax_tree.instr_of_binsec_instr|>Syntax_tree.string_of_expr)|Dba_expr{dba_expr}->Format.fprintffmt"In Dba_expr `%s':@ "(dba_expr|>Binsec2syntax_tree.expr_of_binsec_expr|>Syntax_tree.string_of_expr)|_->assertfalseletpp_loc_stackfmtstack=matchstackwith|[]->()|_->Format.fprintffmt"@[<hv>";List.iter(pp_locfmt)(List.revstack);Format.fprintffmt"@]"let()=Tracelog.set_pp_location_stackpp_loc_stackend