123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425letmc_man={|
# DESCRIPTION
Disassembles a (human readable) string of bytes. This command is the
BAP machine code playground, which is intended to mimic a subset of
llvm-mc functionality, using the BAP disassembly backend. The main
use case is to explore various information associated with the
dissasembled instruction.
# EXAMPLES
The following input formats are supported:
```
0x31 0xd2 0x48 0xf7 0xf3
\\\\x31\\\\xd2\\\\x48\\\\xf7\\\\xf3
31 d2 48 f7 f3
31d248f7f3";
```
|}letobjdump_man={|
# DESCRIPTION
Disassembles and prints a binary using the linear sweep algorithm.
This command is a sibling to the $(b,mc) command, except
that it takes a binary file as an input. If the binary contains only
raw code (i.e., no meta information), then use the $(b,raw) loader.
# EXAMPLES
```
bap objdump /bin/ls --show-asm
bap objdump ./code --loader=raw
```
|}openCore_kernelopenFormatopenRegular.StdopenBap.StdopenBap_plugins.StdopenBap_core_theoryopenBap_mainopenResult.Monad_infixtypeerror=|Bad_user_input|Bad_insnofmem*int*int|Create_memofError.t|No_input|Unknown_arch|Invalid_baseofstring|Trailing_dataofint|InconsistencyofKB.conflict|Unknown_formatofstring*string*stringlist|No_formats_expectedofstring|Disassembler_failedofError.t|Loader_failedofError.ttypeExtension.Error.t+=Failoferrortypeoutput=[|`insn|`bil|`bir|`sema|`kinds|`size|`invalid][@@derivingcompare]letoutputs=[`insn;`bil;`bir;`sema;`kinds;`size;`invalid;]letfailerr=Error(Failerr)letenabled="enabled"moduleSpec=structopenExtensionletinput=Command.argumentsType.stringletfile=Command.argumentType.fileletarch_type=Type.define~parse:(funs->matchArch.of_stringswith|None->invalid_arg"unknown architecture"|Somearch->arch)~print:Arch.to_string`x86_64letarch=letdoc="Target architecture"inCommand.parameter~docarch_type"arch"letoutputs=letname_of_output=function|`insn->"insn"|`bil->"bil"|`bir->"bir"|`sema->"sema"|`kinds->"kinds"|`size->"size"|`invalid->"invalid"inletas_flag=function|`insn|`bil|`bir->["pretty"]|`sema->["all-slots"]|`kinds|`size|`invalid->[enabled]inletdoc=function|`insn->"Print the decoded instruction."|`bil->"Print the BIL code."|`bir->"Print the IR."|`sema->"Print the knowledge base."|`kinds->"Print semantics tags associated with instruction."|`size->"Print the instruction size."|`invalid->"Print invalid instructions."inletnames="show-"^name_of_outputsinExtension.Command.dictionary~doc~as_flagoutputsType.(liststring)nameletbase=letdoc="Specify an address of first byte"inCommand.parameter~aliases:["b"]~docType.string"address"letonly_one=letdoc="Stop after the first instruction is decoded"inCommand.flag~doc"only-one"letstop_on_error=Command.flag"stop-on-errors"~doc:"Stop disassembling on the first error and report it"letbackend=letdoc="Specify the disassembler backend"inCommand.parameter~docType.(somestring)"backend"letloader=Extension.Command.parameter~doc:"Use the specified loader .
Use the loader `raw' to load unstructured files"Extension.Type.(string=?"llvm")"loader"endmoduleDis=Disasm_expert.Basicletbad_insnaddrstatestart=letstop=Addr.(Dis.addrstate-addr|>to_int|>ok_exn)infail(Bad_insn(Dis.memorystate,start,stop))letescape_0x=String.substr_replace_all~pattern:"0x"~with_:"\\x"letprepend_slash_xx="\\x"^x(** [to_binary ?escape s] make a binary string from ascii
representation, (e.g., "\x01\x02..."). Apply optional
escape function for each byte *)letto_binary?(map=ident)s=letseps=[' ';',';';']inletseparated=List.existsseps~f:(String.mems)inletbytes=ifseparatedthenString.split_on_chars~on:sepsselseList.init(String.lengths/2)~f:(funn->String.slices(n*2)(n*2+2))intryList.mapbytes~f:map|>String.concat|>Scanf.unescaped|>Result.returnwith_->failBad_user_inputletread_inputinput=letinput=matchinputwith|[]|["-"]->In_channel.input_lineIn_channel.stdin|s->Some(String.concats)inmatchinputwith|None->failNo_input|Someinput->matchString.prefixinput2with|""|"\n"->failNo_input|"\\x"->to_binaryinput|"0x"->to_binary~map:escape_0xinput|_->to_binary~map:prepend_slash_xinputletcreate_memoryarchdatabase=letendian=Arch.endianarchinMemory.createendianbase@@Bigstring.of_stringdata|>function|Okr->Okr|Errore->fail(Create_meme)letprint_kindsformatsinsn=List.iterformats~f:(fun_->Dis.Insn.kindsinsn|>List.map~f:sexp_of_kind|>List.iter~f:(printf"%a@."Sexp.pp))letnew_insnarchmeminsn=letopenKB.SyntaxinKB.Object.createTheory.Program.cls>>=funcode->KB.provideArch.slotcodearch>>=fun()->KB.provideMemory.slotcode(Somemem)>>=fun()->KB.provideDis.Insn.slotcode(Someinsn)>>|fun()->codeletliftarchmeminsn=matchKB.runTheory.Program.cls(new_insnarchmeminsn)KB.emptywith|Ok(code,_)->Ok(KB.Value.getTheory.Program.Semantics.slotcode)|Errorconflict->fail(Inconsistencyconflict)letprint_insn_sizeformatsmem=List.iterformats~f:(fun_fmt->printf"%#x@\n"(Memory.lengthmem))letprint_insninsn_formatsinsn=List.iterinsn_formats~f:(funfmt->Insn.with_printerfmt(fun()->printf"%a@."Insn.ppinsn))letprint_bilformatsinsn=letbil=Insn.bilinsninList.iterformats~f:(funfmt->printf"%s@."(Bytes.to_string@@Bil.to_bytes~fmtbil))letprint_birformatsinsn=letbs=Blk.from_insninsninList.iterformats~f:(funfmt->printf"%s"@@String.concat~sep:"\n"(List.mapbs~f:(funb->Bytes.to_string@@Blk.to_bytes~fmtb)))letprint_semaformatssema=matchformatswith|[]->()|["all-slots"]->printf"%a@\n"KB.Value.ppsema|some_slots->letpp=KB.Value.pp_slotssome_slotsinprintf"%a@\n"ppsemaletequal_output=[%compare.equal:output]letis_enabled=function|[opt]->String.equalenabledopt|_->falseletformatsoutputskind=matchList.Assoc.findoutputskind~equal:equal_outputwith|None->[]|Somefmts->fmtsletprintarchmemcodeformats=liftarchmemcode>>|funinsn->print_insn_size(formats`size)mem;print_insn(formats`insn)insn;print_bil(formats`bil)insn;print_bir(formats`bir)insn;print_sema(formats`sema)insn;print_kinds(formats`kinds)codeletparse_basearchbase=Result.map_error~f:(function|Invalid_argumentstr->Fail(Invalid_basestr)|exn->Fail(Invalid_base(Exn.to_stringexn)))@@Result.try_with@@fun()->Word.create(Bitvec.of_stringbase)(Size.in_bits(Arch.addr_sizearch))letcreate_disassembler?(backend="llvm")arch=Dis.create~backend(Arch.to_stringarch)|>Result.map_error~f:(funerr->Fail(Disassembler_failederr))letmodule_of_kind=function|`insn->"Bap.Std.Insn"|`bil->"Bap.Std.Bil"|`bir->"Bap.Std.Blk"letvalidate_modulekindformats=letname=module_of_kindkindinData.all_writers()|>List.find_map~f:(fun(modname,fmts)->Option.some_if(String.equalmodnamename)fmts)|>function|None->failwithf"Unable to find printers for module %s"name()|Somefmts->letfmts=List.mapfmts~f:(fun(n,_,_)->n)inletprovided=Set.of_list(moduleString)fmtsinResult.all_unit@@List.mapformats~f:(funfmt->ifSet.memprovidedfmtthenOk()elseError(Unknown_format(name,fmt,fmts)))letvalidate_formatsformats=Result.map_error~f:(funerr->Failerr)@@Result.all_unit@@List.mapformats~f:(function|(`insn|`bil|`bir)askind,fmts->validate_modulekindfmts|(`kinds|`size|`invalid),[]->Ok()|(`kinds|`size|`invalid),[opt]whenString.equalenabledopt->Ok()|`kinds,_->Error(No_formats_expected"kinds")|`size,_->Error(No_formats_expected"size")|`invalid,_->Error(No_formats_expected"invalid")|`sema,_->(* no validation right now, since the knowledge introspection
is not yet implemented *)Ok())letprint_invalid_pos=Format.printf"<invalid>@\n"letrun?(only_one=false)?(stop_on_error=false)disarchmemformats=letshow_invalid=is_enabled(formats`invalid)inDis.rundismem~init:0~return:Result.return~stop_on:[`Valid]~invalid:(funstate_pos->ifshow_invalidthenprint_invalidpos;ifstop_on_errorthenbad_insn(Memory.min_addrmem)stateposelseDis.stepstatepos)~hit:(funstatememinsnbytes->printarchmeminsnformats>>=fun()->ifonly_onethenDis.stopstatebyteselseDis.stepstate(bytes+Memory.lengthmem))let()=Extension.Command.(begindeclare~doc:mc_man"mc"Spec.(args$arch$base$backend$only_one$stop_on_error$input$outputs)end)@@funarchbasebackendonly_onestop_on_errorinputoutputs_ctxt->validate_formatsoutputs>>=fun()->parse_basearchbase>>=funbase->read_inputinput>>=fundata->create_memoryarchdatabase>>=funmem->create_disassembler?backendarch>>=fundis->letformats=formatsoutputsinrun~only_one~stop_on_errordisarchmemformats>>=funbytes->Dis.closedis;matchString.lengthdata-byteswith|0->Ok()|_whenonly_one->Ok()|n->fail(Trailing_datan)let()=Extension.Command.(begindeclare~doc:objdump_man"objdump"Spec.(args$backend$loader$stop_on_error$file$outputs)end)@@funbackendloaderstop_on_errorinputoutputs_ctxt->validate_formatsoutputs>>=fun()->letformats=formatsoutputsinmatchImage.create~backend:loaderinputwith|Errorerr->Error(Fail(Loader_failederr))|Ok(img,_warns)->letarch=Image.archimgincreate_disassembler?backendarch>>=fundis->Image.memoryimg|>Memmap.to_sequence|>Seq.filter_map~f:(fun(mem,data)->Option.some_if(Value.isImage.code_regiondata)mem)|>Seq.map~f:(funmem->run~stop_on_errordisarchmemformats>>=fun_bytes->Ok())|>Seq.to_list|>Result.all_unitletformat_infoget_fmts=get_fmts()|>List.map~f:fst3|>String.concat~sep:", "letstring_of_failure=function|Inconsistencyconflict->Format.asprintf"Lifters failed with a conflict: %a"KB.Conflict.ppconflict|Bad_user_input->"Could not parse: malformed input"|No_input->"No input was received"|Unknown_arch->sprintf"Unknown architecture. Supported architectures:\n%s"@@String.concat~sep:"\n"@@List.mapArch.all~f:Arch.to_string|Trailing_data1->"the last byte wasn't disassembled"|Trailing_dataleft->sprintf"%d bytes were left non disassembled"left|Create_memerr->Format.asprintf"Unable to create a memory: %a"Error.pperr|Invalid_basemsg->sprintf"Failed to parse the base address: %s"msg|Disassembler_failederr->Format.asprintf"Failed to create the disassembler backend: %a"Error.pperr|Bad_insn(mem,boff,stop)->letdump=Memory.hexdumpmem|>Bytes.of_stringinletline=boff/16inletposoff=line*77+(offmod16)*3+9inBytes.setdump(posboff)'(';Bytes.setdump(posstop)')';sprintf"Invalid instruction at offset %d:\n%s"boff(Bytes.to_stringdump)|Unknown_format(mname,fmt,fmts)->letpp_sep=Format.pp_print_newlineinFormat.asprintf"@[<v2>Unknown printer %s for %s, expecting: %a@]"fmtmnameFormat.(pp_print_list~pp_seppp_print_string)fmts|No_formats_expectedname->sprintf"--show-%s doesn't expect any formats yet"name|Loader_failederr->Format.asprintf"Failed to unpack the file: %a"Error.pperrlet()=Extension.Error.register_printer@@function|Failerr->Some(string_of_failureerr)|_->None