From 5a18cda21e0f6c1ff0168761f5d33ffceb880b75 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Wed, 2 Sep 2026 17:04:43 +0000 Subject: [PATCH] GP-7062: final pass GP-7062: comments on intent GP-7062: post-review GP-7062: cleanup GP-7062: rename GP-7062: edges GP-7062: slight revert; bug fix GP-7062: single function task GP-7062: first pass GP-7062: some progressGP-7062: workingishGP-7062: works for geditGP-7062: script -> classesGP-7062: script -> classesGP-7062: typesGP-7062: towards testingGP-7062: towards testingGP-7062: datalog addsGP-7062: datalog addsGP-7062: slow progressGP-7062: getting thereGP-7062: better vnode logicGP-7062: better vnode logicGP-7062: yay, working (at least a little)GP-7062: sane PCODE_ resultsGP-7062: on to sarif resultsGP-7062: sarif workingGP-7062: maybe fixed?GP-7062: mo' betta'GP-7062: probably a lot more to doGP-7062: cleanup for hvar/vnode --- .../certification.manifest | 4 + .../data/ctadl/declarations_ext.dl | 192 +++++ .../data/ctadl/import_ext.dl | 232 ++++++ .../data/ctadl/pcode_lang.rs | 709 ++++++++++++++++++ .../data/ctadl/pcode_lang_ext.dl | 489 ++++++++++++ .../ExportFunctionPcodeViaDecoderScript.java | 61 ++ .../ghidra_scripts/ExportPCodeForCTADL.java | 2 +- .../ExportPcodeViaDecoderScript.java | 56 ++ .../decompiler/export/BasePcodeExporter.java | 62 ++ .../decompiler/export/DecoderMethods.java} | 27 +- .../export/ExportDecompInterface.java | 83 ++ .../export/ExportDecompilationTask.java | 158 ++++ .../export/ExportDecompilerConfigurer.java | 37 + .../export/ExportableDecompileResults.java | 211 ++++++ .../decompiler/export/PcodeAttributes.java | 424 +++++++++++ .../core/decompiler/export/PcodeDatabase.java | 121 +++ .../core/decompiler/export/PcodeElements.java | 511 +++++++++++++ .../core/decompiler/export/PcodeExporter.java | 312 ++++++++ .../decompiler/taint/TaintQueryResult.java | 5 +- .../sarif/SarifTaintGraphRunHandler.java | 5 +- 20 files changed, 3683 insertions(+), 18 deletions(-) create mode 100644 Ghidra/Features/DecompilerDependent/data/ctadl/declarations_ext.dl create mode 100644 Ghidra/Features/DecompilerDependent/data/ctadl/import_ext.dl create mode 100644 Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang.rs create mode 100644 Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang_ext.dl create mode 100644 Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportFunctionPcodeViaDecoderScript.java create mode 100644 Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPcodeViaDecoderScript.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/BasePcodeExporter.java rename Ghidra/Features/DecompilerDependent/{ghidra_scripts/ExportPCodeForSingleFunction.java => src/main/java/ghidra/app/plugin/core/decompiler/export/DecoderMethods.java} (55%) create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompInterface.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilationTask.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilerConfigurer.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportableDecompileResults.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeAttributes.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeDatabase.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeElements.java create mode 100644 Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeExporter.java diff --git a/Ghidra/Features/DecompilerDependent/certification.manifest b/Ghidra/Features/DecompilerDependent/certification.manifest index 5e08aeb77e..8e9832b5c6 100644 --- a/Ghidra/Features/DecompilerDependent/certification.manifest +++ b/Ghidra/Features/DecompilerDependent/certification.manifest @@ -2,6 +2,10 @@ Module.manifest||GHIDRA||||END| README.md||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| +data/ctadl/declarations_ext.dl||GHIDRA||||END| +data/ctadl/import_ext.dl||GHIDRA||||END| +data/ctadl/pcode_lang.rs||GHIDRA||||END| +data/ctadl/pcode_lang_ext.dl||GHIDRA||||END| data/decompiler.dependent.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html||GHIDRA||||END| diff --git a/Ghidra/Features/DecompilerDependent/data/ctadl/declarations_ext.dl b/Ghidra/Features/DecompilerDependent/data/ctadl/declarations_ext.dl new file mode 100644 index 0000000000..b910cf4f95 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/data/ctadl/declarations_ext.dl @@ -0,0 +1,192 @@ +// This file will eventually be incorporate upstream in the CTADL project. +// It resides here purely to facilitate coordination. +#pragma once + +// UTILITY VARIABLES +.decl pcode_id(id: PCodeInstruction, rep: symbol) +.decl vnode_id(id: symbol, addr: symbol) +.decl varnode_hfunc(id: symbol, hfunc_id: PCodeHighFunc) +.decl varnode_hvar(id: symbol, hvar_id: symbol) +.decl op_hfunc(id: symbol, hfunc_id: PCodeHighFunc) +.decl bb_hfunc(id: symbol, hfunc_id: PCodeHighFunc) +.decl location_hfunc(id: symbol, hfunc_id: PCodeHighFunc) +.decl tmp(key: symbol, val: symbol) + +.decl HFUNC_FUNCX(id: PCodeHighFunc, f: symbol) +.decl HFUNC_NAMEX(id: PCodeHighFunc, f: symbol) +.decl HFUNC_ISEXTX(id: PCodeHighFunc) +.decl HFUNC_PROTOX(id: PCodeHighFunc, proto: PCodeHighPrototype) +.decl HFUNC_EPX(id: PCodeHighFunc, ep: symbol) +.decl HFUNC_LOCAL_EPX(id: symbol, addr: symbol) +//.decl HFUNC_ISEXTX(id: PCodeHighFunc) + +.decl BB_EDGE(from: PCodeBlockBasic, to: PCodeBlockBasic) +.decl BB_FIRSTX(bbid: PCodeBlockBasic, id: PCodeInstruction) +.decl BB_HFUNCX(bbid: PCodeBlockBasic, f: PCodeHighFunc) + +.decl hvar_hfunc(id: symbol, vnode_id: symbol) +.decl HVAR_NAMEX(id: symbol, name: symbol) +.decl HVAR_TYPEX(id: symbol, type: PCodeType) +.decl HVAR_REPRESENTATIVEX(id: symbol, vnode_id: symbol) + +.decl PCODE_MNEMONICX(id: PCodeInstruction, mnemonic: symbol) +.decl PCODE_PARENTX(id: PCodeInstruction, bbid: PCodeBlockBasic) +.decl PCODE_TARGETX(id: PCodeInstruction, target_address: symbol) +.decl PCODE_INPUTX(id: PCodeInstruction, i: number, vnode_id: symbol) +.decl PCODE_OUTPUTX(id: PCodeInstruction, vnode_id: symbol) +.decl PCODE_OPCODEX(id: PCodeInstruction, opcode: symbol) +.decl PCODE_NEXTX(prev: PCodeInstruction, next: PCodeInstruction) +.decl PCODE_INDEXX(prev: PCodeInstruction, i: number) + +.decl VNODE_ADDRESSX(id: symbol, address: symbol) +.decl VNODE_PC_ADDRESSX(id: symbol, pc_address: symbol) +.decl VNODE_OFFSETX(id: symbol, offset: symbol) +.decl VNODE_OFFSET_NX(id: symbol, offset: symbol) +.decl VNODE_SIZEX(id: symbol, size: number) +.decl VNODE_SPACEX(id: symbol, space: symbol) +.decl VNODE_HVARX(id: symbol, hvar_id: symbol) +.decl VNODE_HFUNCX(id: symbol, hfunc_id: PCodeHighFunc) +.decl VNODE_NAMEX(id: symbol, vn: symbol) + +.decl OFFSET_INDEXX(offset: symbol, idx: number) + +.decl PROTO_IS_CONSTRUCTORX(id: PCodeHighPrototype) +.decl PROTO_IS_DESTRUCTORX(id: PCodeHighPrototype) +.decl PROTO_IS_VARARGX(id: PCodeHighPrototype) +.decl PROTO_IS_INLINEX(id: PCodeHighPrototype) +.decl PROTO_IS_VOIDX(id: PCodeHighPrototype) +.decl PROTO_HAS_THISX(id: PCodeHighPrototype) +.decl PROTO_CALLING_CONVENTIONX(id: PCodeHighPrototype, cc: PCodeGenericCallingConvention) +.decl PROTO_RETTYPEX(id: PCodeHighPrototype, retty: symbol) +.decl PROTO_PARAMETERX(id: PCodeHighPrototype, n: number, p: PCodeHighSymbol) +.decl PROTO_PARAMETER_COUNTX(id: PCodeHighPrototype, n: number) +.decl PROTO_PARAMETER_DATATYPEX(id: PCodeHighSymbol, type: symbol) + +.decl SYMBOL_HVARX(id: PCodeHighSymbol, hvar_id: PCodeHighVar) +.decl SYMBOL_HFUNCX(id: PCodeHighSymbol, hfunc_id: PCodeHighFunc) +.decl SYMBOL_NAMEX(id: PCodeHighSymbol, name: symbol) + +.decl LOCATION_NUM(addr: symbol, off: symbol) +.decl LOCATION_HEX(addr: symbol, off: symbol) +.decl LOCATION_FUNC(addr: symbol, fn: PCodeHighFunc) +.decl LOCATION_UNIQ(addr: symbol, uniq: number) +.decl MNEMONICS(n: symbol, mnem: symbol) +.decl VARIABLE_FIELD(id: symbol, f: symbol) + +.decl FUNC_ISEXT(id: PCodeHighFunc) +.decl FUNC_PARAMETER(id: PCodeHighFunc, n: number, p: PCodeHighSymbol) +.decl FUNC_PARAMETER_COUNT(id: PCodeHighFunc, n: number) +.decl FUNC_PARAMETER_DATATYPE(id: PCodeHighSymbol, n: number, type: symbol) + +.decl A_ADDR_REF(addr: symbol, ref: number) +.decl A_ADDR_SIZE(addr: symbol, sz: number) +.decl A_ADDR_OFFSET(addr: symbol, off: symbol) +.decl A_ADDR_SPACE(addr: symbol, sp: symbol) + +.decl E_AST_BLOCK(ast: symbol, bbid: PCodeBlockBasic) +.decl E_AST_VARNODES(ast: symbol, id: symbol) + +.decl A_BLOCK_INDEX(id: PCodeBlockBasic, index: number) +.decl E_BLOCK_BLOCK(id: PCodeBlockBasic, bbid: PCodeBlockBasic) +.decl E_BLOCK_OP(bbid: PCodeBlockBasic, id: PCodeInstruction) +.decl E_BLOCK_RANGELIST(id: PCodeBlockBasic, list: symbol) +.decl E_BLOCK_STATEMENT(id: PCodeBlockBasic, s: symbol) +.decl E_BLOCK_VARIABLE(id: PCodeBlockBasic, v: symbol) + +.decl A_BLOCKEDGE_INDEX(id: symbol, index: number) +.decl E_BLOCKEDGE_EDGE(id: symbol, edge: symbol) + +.decl E_DOC_FUNCTION(id: PCodeHighFunc, f: symbol) + +.decl A_EDGE_END(id: symbol, end: number) + +.decl A_FIELD_XMLCONTENT(id: symbol, xml: symbol) + +.decl E_FUNCTION_ADDR(id: symbol, addr: symbol) +.decl E_FUNCTION_AST(id: symbol, ast: symbol) +.decl E_FUNCTION_BLOCK(id: symbol, bbid: PCodeBlockBasic) +.decl E_FUNCTION_FUNCPROTO(id: symbol, proto: PCodeHighPrototype) +.decl E_FUNCTION_HIGHLIST(id: symbol, list: symbol) +.decl E_FUNCTION_LOCALDB(id: symbol, db: symbol) +.decl A_FUNCTION_NAME(id: symbol, name: symbol) +.decl E_FUNCTION_VARDECL(id: symbol, decl: symbol) + +.decl E_FUNCPROTO_VARDECL(id: PCodeHighPrototype, decl: symbol) + +.decl E_HIGH_ADDR(id: PCodeHighVar, addr: symbol) +.decl A_HIGH_CLASS(id: PCodeHighVar, cls: symbol) +.decl A_HIGH_REPREF(id: PCodeHighVar, ref: number) +.decl A_HIGH_SYMREF(id: PCodeHighVar, ref: number) +.decl E_HIGH_TYPE(id: PCodeHighVar, type: PCodeType) +.decl E_HIGH_TYPEREF(id: PCodeHighVar, type: PCodeType) +.decl E_HIGHLIST_HIGH(id: symbol, high: PCodeHighVar) + +.decl A_IOP_VALUE(id: symbol, n: symbol) + +.decl A_INPUT_INDEX(id: symbol, n: number) + +.decl E_LOCALDB_SCOPE(db: symbol, scope: symbol) + +.decl E_MAPSYM_SYMBOL(map: symbol, id: PCodeHighSymbol) + +.decl E_OP_ADDR(id: PCodeInstruction, addr: symbol) +.decl A_OP_CODE(id: PCodeInstruction, mn: symbol) +.decl E_OP_IOP(id: PCodeInstruction, val: symbol) +.decl A_OP_INDEX(id: PCodeInstruction, n: number) +.decl E_OP_INPUT(id: PCodeInstruction, vn: symbol) +.decl E_OP_OUTPUT(id: PCodeInstruction, vn: symbol) +.decl A_OP_OPREF(id: PCodeInstruction, ref: number) +.decl E_OP_SEQNUM(id: PCodeInstruction, sq: symbol) +.decl E_OP_SPACEID(id: PCodeInstruction, val: symbol) + +.decl A_PROTOTYPE_CONSTRUCTOR(id: PCodeHighPrototype, val: symbol) +.decl A_PROTOTYPE_DESTRUCTOR(id: PCodeHighPrototype, val: symbol) +.decl A_PROTOTYPE_DOTDOTDOT(id: PCodeHighPrototype, val: symbol) +.decl A_PROTOTYPE_INLINE(id: PCodeHighPrototype, val: symbol) +.decl A_PROTOTYPE_MODEL(id: PCodeHighPrototype, cc: PCodeGenericCallingConvention) +.decl E_PROTOTYPE_RETURNSYM(id: PCodeHighPrototype, ret: symbol) + +.decl E_RANGELIST_RANGE(id: symbol, rng: symbol) +.decl A_RANGE_FIRST(id: symbol, addr: symbol) +.decl A_RANGE_LAST(id: symbol, addr: symbol) + +.decl E_RETURNSYM_VOID(id: symbol, void: symbol) +.decl E_RETURNSYM_TYPE(id: symbol, type: symbol) +.decl E_RETURNSYM_TYPEREF(id: symbol, ref: symbol) + +.decl E_SCOPE_SYMBOLLIST(scope: symbol, list: symbol) + +.decl A_SEQNUM_OFFSET(sq: symbol, target_address: symbol) +.decl A_SEQNUM_OFFSET_N(addr: symbol, off: number) +.decl A_SEQNUM_OFFSET_HEX(addr: symbol, off: symbol) +.decl A_SEQNUM_OFFSET_UNIQ(off: symbol, uniq: number) +.decl A_SEQNUM_UNIQ(sq: symbol, ref: number) + +.decl A_SPACEID_NAME(s: symbol, ref: symbol) + +.decl E_STATEMENT_FIELD(s: symbol, fn: symbol) +.decl E_STATEMENT_FUNCNAME(s: symbol, fn: symbol) +.decl E_STATEMENT_OP(s: symbol, op: PCodeInstruction) +.decl A_STATEMENT_OPREF(s: symbol, ref: number) +.decl E_STATEMENT_VARIABLE(s: symbol, id: symbol) + +.decl E_SYMBOLLIST_MAPSYM(list: symbol, map: symbol) +.decl A_SYMBOL_CAT(id: PCodeHighSymbol, category: number) +.decl A_SYMBOL_INDEX(id: PCodeHighSymbol, index: number) +.decl A_SYMBOL_NAME(id: PCodeHighSymbol, name: symbol) +.decl A_SYMBOL_ID(id: PCodeHighSymbol, ref: number) +.decl E_SYMBOL_TYPE(id: PCodeHighSymbol, type: symbol) +.decl E_SYMBOL_TYPEREF(id: PCodeHighSymbol, ref: symbol) + +.decl A_TYPE_NAME(id: PCodeType, name: symbol) +.decl A_TYPE_METATYPE(id: PCodeType, meta: PCodeType) +.decl A_TYPE_SIZE(id: PCodeType, sz: number) +.decl E_TYPE_TYPEREF(id: PCodeType, ref: symbol) +.decl A_TYPEREF_NAME(id: symbol, name: symbol) + +.decl E_VARDECL_VARIABLE(id: symbol, v: symbol) +.decl A_VARIABLE_OPREF(id: symbol, ref: number) +.decl A_VARIABLE_VARREF(id: symbol, ref: number) +.decl A_VARIABLE_XMLCONTENT(id: symbol, name: symbol) +.decl E_VARNODES_ADDR(id: symbol, addr: symbol) + diff --git a/Ghidra/Features/DecompilerDependent/data/ctadl/import_ext.dl b/Ghidra/Features/DecompilerDependent/data/ctadl/import_ext.dl new file mode 100644 index 0000000000..3503477ad2 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/data/ctadl/import_ext.dl @@ -0,0 +1,232 @@ +// This file will eventually be incorporate upstream in the CTADL project. +// It resides here purely to facilitate coordination. + +.input LOCATION_NUM(filename="LOCATION_NUM.facts") +.input LOCATION_HEX(filename="LOCATION_HEX.facts") +.input LOCATION_FUNC(filename="LOCATION_FUNC.facts") +.input LOCATION_UNIQ(filename="LOCATION_UNIQ.facts") + +.input MNEMONICS(filename="MNEMONICS.facts") +.input VARIABLE_FIELD(filename="VARIABLE_FIELD.facts") + +.input FUNC_ISEXT(filename="FUNC_ISEXT.facts") +.input FUNC_PARAMETER(filename="FUNC_PARAMETER.facts") +.input FUNC_PARAMETER_COUNT(filename="FUNC_PARAMETER_COUNT.facts") +.input FUNC_PARAMETER_DATATYPE(filename="FUNC_PARAMETER_DATATYPE.facts") + + +// ATTRIBUTES + +.input A_ADDR_OFFSET(filename="A_ADDR_OFFSET.facts") +.input A_ADDR_REF(filename="A_ADDR_REF.facts") +.input A_ADDR_SIZE(filename="A_ADDR_SIZE.facts") +.input A_ADDR_SPACE(filename="A_ADDR_SPACE.facts") + +.input A_BLOCK_INDEX(filename="A_BLOCK_INDEX.facts") + +.input A_BLOCKEDGE_INDEX(filename="A_BLOCKEDGE_INDEX.facts") + +// input is a varnode +.input A_INPUT_INDEX(filename="A_INPUT_INDEX.facts") + +.input A_FIELD_XMLCONTENT(filename="A_FIELD_XMLCONTENT.facts") + +.input A_EDGE_END(filename="A_EDGE_END.facts") + +.input A_FUNCTION_NAME(filename="A_FUNCTION_NAME.facts") + +.input A_HIGH_CLASS(filename="A_HIGH_CLASS.facts") +.input A_HIGH_REPREF(filename="A_HIGH_REPREF.facts") +.input A_HIGH_SYMREF(filename="A_HIGH_SYMREF.facts") + +.input A_IOP_VALUE(filename="A_IOP_VALUE.facts") + +.input A_OP_CODE(filename="A_OP_CODE.facts") +.input A_OP_OPREF(filename="A_OP_OPREF.facts") +.input A_OP_INDEX(filename="A_OP_INDEX.facts") + +.input A_PROTOTYPE_MODEL(filename="A_PROTOTYPE_MODEL.facts") +.input A_PROTOTYPE_CONSTRUCTOR(filename="A_PROTOTYPE_CONSTRUCTOR.facts") +.input A_PROTOTYPE_DESTRUCTOR(filename="A_PROTOTYPE_DESTRUCTOR.facts") +.input A_PROTOTYPE_DOTDOTDOT(filename="A_PROTOTYPE_DOTDOTDOT.facts") +.input A_PROTOTYPE_INLINE(filename="A_PROTOTYPE_INLINE.facts") +.input A_PROTOTYPE_MODEL(filename="A_PROTOTYPE_MODEL.facts") + +.input A_RANGE_FIRST(filename="A_RANGE_FIRST.facts") +.input A_RANGE_LAST(filename="A_RANGE_LAST.facts") + +.input A_SEQNUM_OFFSET(filename="A_SEQNUM_OFFSET.facts") +.input A_SEQNUM_UNIQ(filename="A_SEQNUM_UNIQ.facts") + +.input A_SPACEID_NAME(filename="A_SPACEID_NAME.facts") + +.input A_STATEMENT_OPREF(filename="A_STATEMENT_OPREF.facts") + +.input A_SYMBOL_CAT(filename="A_SYMBOL_CAT.facts") +.input A_SYMBOL_ID(filename="A_SYMBOL_ID.facts") +.input A_SYMBOL_INDEX(filename="A_SYMBOL_INDEX.facts") +.input A_SYMBOL_NAME(filename="A_SYMBOL_NAME.facts") + +.input A_TYPE_METATYPE(filename="A_TYPE_METATYPE.facts") +.input A_TYPE_NAME(filename="A_TYPE_NAME.facts") +.input A_TYPE_SIZE(filename="A_TYPE_SIZE.facts") +.input A_TYPEREF_NAME(filename="A_TYPEREF_NAME.facts") + +.input A_VARIABLE_OPREF(filename="A_VARIABLE_OPREF.facts") +.input A_VARIABLE_VARREF(filename="A_VARIABLE_VARREF.facts") +.input A_VARIABLE_XMLCONTENT(filename="A_VARIABLE_XMLCONTENT.facts") + + +// ELEMENTS + +.input E_AST_BLOCK(filename="E_AST_BLOCK.facts") +.input E_AST_VARNODES(filename="E_AST_VARNODES.facts") + +.input E_BLOCK_BLOCK(filename="E_BLOCK_BLOCK.facts") +.input E_BLOCK_OP(filename="E_BLOCK_OP.facts") +.input E_BLOCK_RANGELIST(filename="E_BLOCK_RANGELIST.facts") +.input E_BLOCK_STATEMENT(filename="E_BLOCK_STATEMENT.facts") +.input E_BLOCK_VARIABLE(filename="E_BLOCK_VARIABLE.facts") + +.input E_BLOCKEDGE_EDGE(filename="E_BLOCKEDGE_EDGE.facts") + +.input E_DOC_FUNCTION(filename="E_DOC_FUNCTION.facts") + +.input E_FUNCPROTO_VARDECL(filename="E_FUNCPROTO_VARDECL.facts") + +.input E_FUNCTION_ADDR(filename="E_FUNCTION_ADDR.facts") +.input E_FUNCTION_AST(filename="E_FUNCTION_AST.facts") +.input E_FUNCTION_BLOCK(filename="E_FUNCTION_BLOCK.facts") +.input E_FUNCTION_FUNCPROTO(filename="E_FUNCTION_FUNCPROTO.facts") +.input E_FUNCTION_HIGHLIST(filename="E_FUNCTION_HIGHLIST.facts") +.input E_FUNCTION_LOCALDB(filename="E_FUNCTION_LOCALDB.facts") +.input E_FUNCTION_VARDECL(filename="E_FUNCTION_VARDECL.facts") + +.input E_HIGH_ADDR(filename="E_HIGH_ADDR.facts") +.input E_HIGH_TYPE(filename="E_HIGH_TYPE.facts") +.input E_HIGH_TYPEREF(filename="E_HIGH_TYPEREF.facts") +.input E_HIGHLIST_HIGH(filename="E_HIGHLIST_HIGH.facts") + +.input E_LOCALDB_SCOPE(filename="E_LOCALDB_SCOPE.facts") + +.input E_MAPSYM_SYMBOL(filename="E_MAPSYM_SYMBOL.facts") + +.input E_OP_ADDR(filename="E_OP_ADDR.facts") +.input E_OP_IOP(filename="E_OP_IOP.facts") +.input E_OP_SEQNUM(filename="E_OP_SEQNUM.facts") +.input E_OP_SPACEID(filename="E_OP_SPACEID.facts") +.input E_OP_OUTPUT(filename="E_OP_OUTPUT.facts") +.input E_OP_INPUT(filename="E_OP_INPUT.facts") + +.input E_PROTOTYPE_RETURNSYM(filename="E_PROTOTYPE_RETURNSYM.facts") + +.input E_RANGELIST_RANGE(filename="E_RANGELIST_RANGE.facts") + +.input E_RETURNSYM_TYPE(filename="E_RETURNSYM_TYPE.facts") +.input E_RETURNSYM_TYPEREF(filename="E_RETURNSYM_TYPEREF.facts") +.input E_RETURNSYM_VOID(filename="E_RETURNSYM_VOID.facts") + +.input E_SCOPE_SYMBOLLIST(filename="E_SCOPE_SYMBOLLIST.facts") + +.input E_STATEMENT_FIELD(filename="E_STATEMENT_FIELD.facts") +.input E_STATEMENT_FUNCNAME(filename="E_STATEMENT_FUNCNAME.facts") +.input E_STATEMENT_OP(filename="E_STATEMENT_OP.facts") +.input E_STATEMENT_VARIABLE(filename="E_STATEMENT_VARIABLE.facts") + +.input E_SYMBOLLIST_MAPSYM(filename="E_SYMBOLLIST_MAPSYM.facts") +.input E_SYMBOL_TYPE(filename="E_SYMBOL_TYPE.facts") +.input E_SYMBOL_TYPEREF(filename="E_SYMBOL_TYPEREF.facts") + +.input E_TYPE_TYPEREF(filename="E_TYPE_TYPEREF.facts") + +.input E_VARDECL_VARIABLE(filename="E_VARDECL_VARIABLE.facts") + +.input E_VARNODES_ADDR(filename="E_VARNODES_ADDR.facts") + +// UNUSED (SO FAR) + +//.input A_ADDR_ADDRTIED(filename="A_ADDR_ADDRTIED.facts") +//.input A_ADDR_GRP(filename="A_ADDR_GRP.facts") +//.input A_ADDR_INPUT(filename="A_ADDR_INPUT.facts") +//.input A_ADDR_PERSISTS(filename="A_ADDR_PERSISTS.facts") +//.input A_ADDR_UNAFF(filename="A_ADDR_UNAFF.facts") +//.input A_BLOCK_BLOCKREF(filename="A_BLOCK_BLOCKREF.facts") +//.input A_BREAK_INDENT(filename="A_BREAK_INDENT.facts") +//.input A_COMMENT_COLOR(filename="A_COMMENT_COLOR.facts") +//.input A_COMMENT_OFF(filename="A_COMMENT_OFF.facts") +//.input A_COMMENT_SPACE(filename="A_COMMENT_SPACE.facts") +//.input A_COMMENT_XMLCONTENT(filename="A_COMMENT_XMLCONTENT.facts") +//.input A_EDGE_REV(filename="A_EDGE_REV.facts") +//.input A_FUNCNAME_COLOR(filename="A_FUNCNAME_COLOR.facts") +//.input A_FUNCNAME_OPREF(filename="A_FUNCNAME_OPREF.facts") +//.input A_FUNCNAME_XMLCONTENT(filename="A_FUNCNAME_XMLCONTENT.facts") +//.input A_FUNCTION_SIZE(filename="A_FUNCTION_SIZE.facts") +//.input A_HIGH_OFFSET(filename="A_HIGH_OFFSET.facts") +//.input A_HIGH_TYPELOCK(filename="A_HIGH_TYPELOCK.facts") +//.input A_LOCALDB_LOCK(filename="A_LOCALDB_LOCK.facts") +//.input A_LOCALDB_MAIN(filename="A_LOCALDB_MAIN.facts") +//.input A_OP_COLOR(filename="A_OP_COLOR.facts") +//.input A_OP_XMLCONTENT(filename="A_OP_XMLCONTENT.facts") +//.input A_PARENT_ID(filename="A_PARENT_ID.facts") +//.input A_PROTOTYPE_EXTRAPOP(filename="A_PROTOTYPE_EXTRAPOP.facts") +//.input A_PROTOTYPE_MODELLOCK(filename="A_PROTOTYPE_MODELLOCK.facts") +//.input A_PROTOTYPE_NORETURN(filename="A_PROTOTYPE_NORETURN.facts") +//.input A_RANGE_SPACE(filename="A_RANGE_SPACE.facts") +//.input A_RETURNSYM_TYPELOCK(filename="A_RETURNSYM_TYPELOCK.facts") +//.input A_RETURN_TYPE_VARREF(filename="A_RETURN_TYPE_VARREF.facts") +//.input A_SCOPE_ID(filename="A_SCOPE_ID.facts") +//.input A_SCOPE_NAME(filename="A_SCOPE_NAME.facts") +//.input A_SEQNUM_SPACE(filename="A_SEQNUM_SPACE.facts") +//.input A_SYMBOL_MERGE(filename="A_SYMBOL_MERGE.facts") +//.input A_SYMBOL_NAMELOCK(filename="A_SYMBOL_NAMELOCK.facts") +//.input A_SYMBOL_TYPELOCK(filename="A_SYMBOL_TYPELOCK.facts") +//.input A_SYNTAX_CLOSE(filename="A_SYNTAX_CLOSE.facts") +//.input A_SYNTAX_COLOR(filename="A_SYNTAX_COLOR.facts") +//.input A_SYNTAX_OPEN(filename="A_SYNTAX_OPEN.facts") +//.input A_SYNTAX_XMLCONTENT(filename="A_SYNTAX_XMLCONTENT.facts") +//.input A_TYPE_ARRAYSIZE(filename="A_TYPE_ARRAYSIZE.facts") +//.input A_TYPE_COLOR(filename="A_TYPE_COLOR.facts") +//.input A_TYPE_CORE(filename="A_TYPE_CORE.facts") +//.input A_TYPE_ID(filename="A_TYPE_ID.facts") +//.input A_TYPE_SPACE(filename="A_TYPE_SPACE.facts") +//.input A_TYPE_XMLCONTENT(filename="A_TYPE_XMLCONTENT.facts") +//.input A_TYPEREF_ID(filename="A_TYPEREF_ID.facts") +//.input A_VARDECL_SYMREF(filename="A_VARDECL_SYMREF.facts") +//.input A_VARIABLE_COLOR(filename="A_VARIABLE_COLOR.facts") + +//.input E_AST_BLOCKEDGE(filename="E_AST_BLOCKEDGE.facts") +//.input E_BLOCK_BREAK(filename="E_BLOCK_BREAK.facts") +//.input E_BLOCK_COMMENT(filename="E_BLOCK_COMMENT.facts") +//.input E_BLOCK_SYNTAX(filename="E_BLOCK_SYNTAX.facts") +//.input E_BLOCK_TYPE(filename="E_BLOCK_TYPE.facts") +//.input E_CALLDEST_ADDR(filename="E_CALLDEST_ADDR.facts") +//.input E_FUNCPROTO_FUNCNAME(filename="E_FUNCPROTO_FUNCNAME.facts") +//.input E_FUNCPROTO_RETURN_TYPE(filename="E_FUNCPROTO_RETURN_TYPE.facts") +//.input E_FUNCPROTO_SYNTAX(filename="E_FUNCPROTO_SYNTAX.facts") +//.input E_FUNCTION_BREAK(filename="E_FUNCTION_BREAK.facts") +//.input E_FUNCTION_COMMENT(filename="E_FUNCTION_COMMENT.facts") +//.input E_FUNCTION_OVERRIDE(filename="E_FUNCTION_OVERRIDE.facts") +//.input E_FUNCTION_PROTOTYPE(filename="E_FUNCTION_PROTOTYPE.facts") +//.input E_FUNCTION_SYNTAX(filename="E_FUNCTION_SYNTAX.facts") +//.input E_INTERNALLIST_PARAM(filename="E_INTERNALLIST_PARAM.facts") +//.input E_MAPSYM_ADDR(filename="E_MAPSYM_ADDR.facts") +//.input E_MAPSYM_RANGELIST(filename="E_MAPSYM_RANGELIST.facts") +//.input E_OP_VOID(filename="E_OP_VOID.facts") +//.input E_OVERRIDE_CALLDEST(filename="E_OVERRIDE_CALLDEST.facts") +//.input E_PARAM_TYPE(filename="E_PARAM_TYPE.facts") +//.input E_PROTOTYPE_INTERNALLIST(filename="E_PROTOTYPE_INTERNALLIST.facts") +//.input E_RETURNSYM_ADDR(filename="E_RETURNSYM_ADDR.facts") +//.input E_RETURN_TYPE_OP(filename="E_RETURN_TYPE_OP.facts") +//.input E_RETURN_TYPE_SYNTAX(filename="E_RETURN_TYPE_SYNTAX.facts") +//.input E_RETURN_TYPE_TYPE(filename="E_RETURN_TYPE_TYPE.facts") +//.input E_SCOPE_PARENT(filename="E_SCOPE_PARENT.facts") +//.input E_SCOPE_RANGELIST(filename="E_SCOPE_RANGELIST.facts") +//.input E_STATEMENT_BREAK(filename="E_STATEMENT_BREAK.facts") +//.input E_STATEMENT_SYNTAX(filename="E_STATEMENT_SYNTAX.facts") +//.input E_STATEMENT_TYPE(filename="E_STATEMENT_TYPE.facts") +//.input E_TYPE_ADDR(filename="E_TYPE_ADDR.facts") +//.input E_TYPE_TYPE(filename="E_TYPE_TYPE.facts") +//.input E_VARDECL_OP(filename="E_VARDECL_OP.facts") +//.input E_VARDECL_SYNTAX(filename="E_VARDECL_SYNTAX.facts") +//.input E_VARDECL_TYPE(filename="E_VARDECL_TYPE.facts") + diff --git a/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang.rs b/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang.rs new file mode 100644 index 0000000000..df681a0f14 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang.rs @@ -0,0 +1,709 @@ +// This file will eventually be incorporate upstream in the CTADL project. +// It resides here purely to facilitate coordination. + +use ascent::ascent; +use std::fs::File; +use std::io::{BufRead, BufReader, BufWriter, Write}; +use std::path::Path; + +// ========================================== +// 1. DOMAIN SPECIFIC TYPE ALIASES +// ========================================== +type PCodeInstruction = String; +type PCodeHighFunc = String; +type PCodeHighPrototype = String; +type PCodeBlockBasic = String; +type PCodeType = String; +type PCodeHighSymbol = String; +type PCodeHighVar = String; +type PCodeGenericCallingConvention = String; + + +// ========================================== +// 2. THE ASCENT DATALOG ENGINE BLOCK +// ========================================== +ascent! { + // --- INPUT & UTILITY SCHEMAS --- + relation pcode_id(PCodeInstruction, String); + relation vnode_id(String, String); + relation varnode_hfunc(String, PCodeHighFunc); + relation varnode_hvar(String, String); + relation op_hfunc(String, PCodeHighFunc); + relation bb_hfunc(String, PCodeHighFunc); + relation location_hfunc(String, PCodeHighFunc); + relation tmp(String, String); + + relation HFUNC_FUNCX(PCodeHighFunc, String); + relation HFUNC_NAMEX(PCodeHighFunc, String); + relation HFUNC_ISEXTX(PCodeHighFunc); + relation HFUNC_PROTOX(PCodeHighFunc, PCodeHighPrototype); + relation HFUNC_EPX(PCodeHighFunc, String); + relation HFUNC_LOCAL_EPX(String, String); + + relation BB_EDGE(PCodeBlockBasic, PCodeBlockBasic); + relation BB_FIRSTX(PCodeBlockBasic, PCodeInstruction); + relation BB_HFUNCX(PCodeBlockBasic, PCodeHighFunc); + + relation hvar_hfunc(String, String); + relation HVAR_NAMEX(String, String); + relation HVAR_TYPEX(String, PCodeType); + relation HVAR_REPRESENTATIVEX(String, String); + + relation PCODE_MNEMONICX(PCodeInstruction, String); + relation PCODE_PARENTX(PCodeInstruction, PCodeBlockBasic); + relation PCODE_TARGETX(PCodeInstruction, String); + relation PCODE_INPUTX(PCodeInstruction, usize, String); + relation PCODE_OUTPUTX(PCodeInstruction, String); + relation PCODE_OPCODEX(PCodeInstruction, String); + relation PCODE_NEXTX(PCodeInstruction, PCodeInstruction); + relation PCODE_INDEXX(PCodeInstruction, usize); + + relation VNODE_ADDRESSX(String, String); + relation VNODE_PC_ADDRESSX(String, String); + relation VNODE_OFFSETX(String, String); + relation VNODE_OFFSET_NX(String, String); + relation VNODE_SIZEX(String, usize); + relation VNODE_SPACEX(String, String); + relation VNODE_HVARX(String, String); + relation VNODE_HFUNCX(String, PCodeHighFunc); + relation VNODE_NAMEX(String, String); + + relation OFFSET_INDEXX(String, usize); + + relation PROTO_IS_CONSTRUCTORX(PCodeHighPrototype); + relation PROTO_IS_DESTRUCTORX(PCodeHighPrototype); + relation PROTO_IS_VARARGX(PCodeHighPrototype); + relation PROTO_IS_INLINEX(PCodeHighPrototype); + relation PROTO_IS_VOIDX(PCodeHighPrototype); + relation PROTO_HAS_THISX(PCodeHighPrototype); + relation PROTO_CALLING_CONVENTIONX(PCodeHighPrototype, PCodeGenericCallingConvention); + relation PROTO_RETTYPEX(PCodeHighPrototype, String); + relation PROTO_PARAMETERX(PCodeHighPrototype, usize, PCodeHighSymbol); + relation PROTO_PARAMETER_COUNTX(PCodeHighPrototype, usize); + relation PROTO_PARAMETER_DATATYPEX(PCodeHighSymbol, String); + + relation SYMBOL_HVARX(PCodeHighSymbol, PCodeHighVar); + relation SYMBOL_HFUNCX(PCodeHighSymbol, PCodeHighFunc); + relation SYMBOL_NAMEX(PCodeHighSymbol, String); + + relation LOCATION_NUM(String, String); + relation LOCATION_HEX(String, String); + relation LOCATION_FUNC(String, PCodeHighFunc); + relation LOCATION_UNIQ(String, usize); + relation MNEMONICS(String, String); + relation VARIABLE_FIELD(String, String); + + relation FUNC_ISEXT(PCodeHighFunc); + relation FUNC_PARAMETER(PCodeHighFunc, usize, PCodeHighSymbol); + relation FUNC_PARAMETER_COUNT(PCodeHighFunc, usize); + relation FUNC_PARAMETER_DATATYPE(PCodeHighSymbol, usize, String); + + relation A_ADDR_REF(String, usize); + relation A_ADDR_SIZE(String, usize); + relation A_ADDR_OFFSET(String, String); + relation A_ADDR_SPACE(String, String); + + relation E_AST_BLOCK(String, PCodeBlockBasic); + relation E_AST_VARNODES(String, String); + + relation A_BLOCK_INDEX(PCodeBlockBasic, usize); + relation E_BLOCK_BLOCK(PCodeBlockBasic, PCodeBlockBasic); + relation E_BLOCK_OP(PCodeBlockBasic, PCodeInstruction); + relation E_BLOCK_RANGELIST(PCodeBlockBasic, String); + relation E_BLOCK_STATEMENT(PCodeBlockBasic, String); + relation E_BLOCK_VARIABLE(PCodeBlockBasic, String); + + relation A_BLOCKEDGE_INDEX(String, usize); + relation E_BLOCKEDGE_EDGE(String, String); + + relation E_DOC_FUNCTION(PCodeHighFunc, String); + + relation A_EDGE_END(String, usize); + + relation A_FIELD_XMLCONTENT(String, String); + + relation E_FUNCTION_ADDR(String, String); + relation E_FUNCTION_AST(String, String); + relation E_FUNCTION_BLOCK(String, PCodeBlockBasic); + relation E_FUNCTION_FUNCPROTO(String, PCodeHighPrototype); + relation E_FUNCTION_HIGHLIST(String, String); + relation E_FUNCTION_LOCALDB(String, String); + relation A_FUNCTION_NAME(String, String); + relation E_FUNCTION_VARDECL(String, String); + + relation E_FUNCPROTO_VARDECL(PCodeHighPrototype, String); + + relation E_HIGH_ADDR(PCodeHighVar, String); + relation A_HIGH_CLASS(PCodeHighVar, String); + relation A_HIGH_REPREF(PCodeHighVar, usize); + relation A_HIGH_SYMREF(PCodeHighVar, usize); + relation E_HIGH_TYPE(PCodeHighVar, PCodeType); + relation E_HIGH_TYPEREF(PCodeHighVar, PCodeType); + + relation E_HIGHLIST_HIGH(String, PCodeHighVar); + + relation A_IOP_VALUE(String, String); + + relation A_INPUT_INDEX(String, usize); + + relation E_LOCALDB_SCOPE(String, String); + + relation E_MAPSYM_SYMBOL(String, PCodeHighSymbol); + + relation E_OP_ADDR(PCodeInstruction, String); + relation A_OP_CODE(PCodeInstruction, String); + relation E_OP_IOP(PCodeInstruction, String); + relation A_OP_INDEX(PCodeInstruction, usize); + relation E_OP_INPUT(PCodeInstruction, String); + relation E_OP_OUTPUT(PCodeInstruction, String); + relation A_OP_OPREF(PCodeInstruction, usize); + relation E_OP_SEQNUM(PCodeInstruction, String); + relation E_OP_SPACEID(PCodeInstruction, String); + + relation A_PROTOTYPE_CONSTRUCTOR(PCodeHighPrototype, String); + relation A_PROTOTYPE_DESTRUCTOR(PCodeHighPrototype, String); + relation A_PROTOTYPE_DOTDOTDOT(PCodeHighPrototype, String); + relation A_PROTOTYPE_INLINE(PCodeHighPrototype, String); + relation A_PROTOTYPE_MODEL(PCodeHighPrototype, PCodeGenericCallingConvention); + relation E_PROTOTYPE_RETURNSYM(PCodeHighPrototype, String); + + relation E_RANGELIST_RANGE(String, String); + relation A_RANGE_FIRST(String, String); + relation A_RANGE_LAST(String, String); + + relation E_RETURNSYM_VOID(String, String); + relation E_RETURNSYM_TYPE(String, String); + relation E_RETURNSYM_TYPEREF(String, String); + + relation E_SCOPE_SYMBOLLIST(String, String); + + relation A_SEQNUM_OFFSET(String, String); + relation A_SEQNUM_OFFSET_N(String, usize); + relation A_SEQNUM_OFFSET_HEX(String, String); + relation A_SEQNUM_OFFSET_UNIQ(String, usize); + relation A_SEQNUM_UNIQ(String, usize); + + relation A_SPACEID_NAME(String, String); + + relation E_STATEMENT_FIELD(String, String); + relation E_STATEMENT_FUNCNAME(String, String); + relation E_STATEMENT_OP(String, PCodeInstruction); + relation A_STATEMENT_OPREF(String, usize); + relation E_STATEMENT_VARIABLE(String, String); + + relation E_SYMBOLLIST_MAPSYM(String, String); + + relation A_SYMBOL_CAT(PCodeHighSymbol, usize); + relation A_SYMBOL_INDEX(PCodeHighSymbol, usize); + relation A_SYMBOL_NAME(PCodeHighSymbol, String); + relation A_SYMBOL_ID(PCodeHighSymbol, usize); + relation E_SYMBOL_TYPE(PCodeHighSymbol, String); + relation E_SYMBOL_TYPEREF(PCodeHighSymbol, String); + + relation A_TYPE_NAME(PCodeType, String); + relation A_TYPE_METATYPE(PCodeType, PCodeType); + relation A_TYPE_SIZE(PCodeType, usize); + relation E_TYPE_TYPEREF(PCodeType, String); + relation A_TYPEREF_NAME(String, String); + + relation E_VARDECL_VARIABLE(String, String); + relation A_VARIABLE_OPREF(String, usize); + relation A_VARIABLE_VARREF(String, usize); + relation A_VARIABLE_XMLCONTENT(String, String); + relation E_VARNODES_ADDR(String, String); + + + // --- DERIVED LOGIC RULES --- + location_hfunc(a.clone(), fn_id.clone()) <-- + LOCATION_FUNC(a, fn_id); + + op_hfunc(op.clone(), fn_id.clone()) <-- + E_OP_ADDR(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + op_hfunc(op.clone(), fn_id.clone()) <-- + E_OP_IOP(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + + bb_hfunc(bb.clone(), fn_id.clone()) <-- + E_OP_ADDR(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + bb_hfunc(bb.clone(), fn_id.clone()) <-- + E_OP_IOP(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + + location_hfunc(a.clone(), fn_id.clone()) <-- + E_OP_ADDR(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + location_hfunc(a.clone(), fn_id.clone()) <-- + E_OP_IOP(op, a), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn_id), + E_DOC_FUNCTION(fn_id, _); + + + OFFSET_INDEXX(num.clone(), n) <-- + LOCATION_NUM(off, num), + LOCATION_UNIQ(off, n); + + + VNODE_NAMEX(id.clone(), format!("vn{}", r)) <-- + A_ADDR_REF(a, r), + location_hfunc(a, fn_id), + let id = format!("{}:{}", fn_id, r); + + vnode_id(id.clone(), a.clone()) <-- + A_ADDR_REF(a, r), + location_hfunc(a, fn_id), + let id = format!("{}:{}", fn_id, r); + + VNODE_SPACEX(id.clone(), "const".to_string()) <-- + E_OP_IOP(op, id), + A_IOP_VALUE(id, num); + + VNODE_ADDRESSX(id.clone(), num.clone()) <-- + E_OP_IOP(op, id), + A_IOP_VALUE(id, num); + + VNODE_NAMEX(id.clone(), id.clone()) <-- + E_OP_IOP(op, id), + A_IOP_VALUE(id, num); + + vnode_id(id.clone(), id.clone()) <-- + E_OP_IOP(op, id), + A_IOP_VALUE(id, num); + + VNODE_SPACEX(id.clone(), "const".to_string()) <-- + E_OP_SPACEID(op, id), + A_SPACEID_NAME(id, num); + + VNODE_ADDRESSX(id.clone(), num.clone()) <-- + E_OP_SPACEID(op, id), + A_SPACEID_NAME(id, num); + + VNODE_NAMEX(id.clone(), id.clone()) <-- + E_OP_SPACEID(op, id), + A_SPACEID_NAME(id, num); + + vnode_id(id.clone(), id.clone()) <-- + E_OP_SPACEID(op, id), + A_SPACEID_NAME(id, num); + + VNODE_ADDRESSX(id.clone(), num.clone()) <-- + vnode_id(id, a), + A_ADDR_OFFSET(a, off), + LOCATION_NUM(off, num); + + VNODE_SPACEX(id.clone(), sp.clone()) <-- + vnode_id(id, a), + A_ADDR_SPACE(a, sp); + + VNODE_OFFSETX(id.clone(), off.clone()) <-- + VNODE_ADDRESSX(id, a), + LOCATION_HEX(a, off); + + VNODE_OFFSET_NX(id.clone(), n.clone()) <-- + VNODE_ADDRESSX(id, a), + LOCATION_NUM(a, n); + + VNODE_PC_ADDRESSX(id.clone(), off.clone()) <-- + vnode_id(id, a), + A_ADDR_REF(a, aref), + A_VARIABLE_VARREF(v, aref), + A_VARIABLE_OPREF(v, ref_val), + A_SEQNUM_UNIQ(sq, ref_val), + A_SEQNUM_OFFSET(sq, off); + + VNODE_PC_ADDRESSX(id.clone(), off.clone()) <-- + vnode_id(id, a), + E_OP_OUTPUT(op, a), + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, off); + + VNODE_SIZEX(id.clone(), *sz) <-- + vnode_id(id, a), + A_ADDR_SIZE(a, sz); + + VNODE_SIZEX(id.clone(), *sz) <-- + vnode_id(id, a), + A_ADDR_REF(a, r), + A_HIGH_REPREF(hv, r), + E_HIGH_TYPE(hv, t), + A_TYPE_SIZE(t, sz); + + VNODE_HFUNCX(id.clone(), fn_id.clone()) <-- + vnode_id(id, a), l + ocation_hfunc(a, fn_id); + + VNODE_HVARX(id.clone(), hv.clone()) <-- + vnode_id(id, a), + E_HIGH_ADDR(hv, a); + + + PCODE_MNEMONICX(op.clone(), mn.clone()) <-- + A_OP_CODE(op, n), + MNEMONICS(n, mn); + + PCODE_OPCODEX(op.clone(), n.clone()) <-- + A_OP_CODE(op, n); + + PCODE_INPUTX(op.clone(), *n, id.clone()) <-- + E_OP_INPUT(op, addr), + vnode_id(id, addr), + A_INPUT_INDEX(addr, n); + + PCODE_OUTPUTX(op.clone(), id.clone()) <-- + E_OP_OUTPUT(op, addr), + vnode_id(id, addr); + + PCODE_TARGETX(op.clone(), addr.clone()) <-- + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, addr); + + PCODE_PARENTX(op.clone(), p.clone()) <-- + A_OP_CODE(op, _), + E_BLOCK_OP(p, op); + + PCODE_NEXTX(op.clone(), nxt.clone()) <-- + E_OP_SEQNUM(op, opsq), + E_BLOCK_OP(block, op), + E_BLOCK_OP(block, nxt), + A_OP_INDEX(op, opn), + A_OP_INDEX(nxt, nxtn), + if *nxtn == *opn + 1; + + pcode_id(op.clone(), format!("{}:{}", addr, ref_val)) <-- + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, addr), + A_OP_INDEX(op, ref_val); + + PCODE_INDEXX(op.clone(), *idx) <-- + A_OP_INDEX(op, idx); + + + SYMBOL_NAMEX(hs.clone(), name.clone()) <-- + A_SYMBOL_NAME(hs, name); + + SYMBOL_HVARX(hs.clone(), hv.clone()) <-- + A_HIGH_SYMREF(hv, r), + A_SYMBOL_ID(hs, r), + hvar_hfunc(hv, fn_id), + SYMBOL_HFUNCX(hs, fn_id); + + SYMBOL_HFUNCX(hs.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_LOCALDB(f, db), + E_LOCALDB_SCOPE(db, scope), + E_SCOPE_SYMBOLLIST(scope, list), + E_SYMBOLLIST_MAPSYM(list, map), + E_MAPSYM_SYMBOL(map, hs); + + + hvar_hfunc(hv.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_HIGHLIST(f, list), + E_HIGHLIST_HIGH(list, hv); + + HVAR_NAMEX(hv.clone(), name.clone()) <-- + SYMBOL_HVARX(sym, hv), + A_SYMBOL_NAME(sym, name); + + HVAR_NAMEX(hv.clone(), name.clone()) <-- + varnode_hvar(v, hv), + A_VARIABLE_XMLCONTENT(v, name); + + HVAR_NAMEX(hv.clone(), format!("{}.{}", prefix, suffix)) <-- + varnode_hvar(v, hv), + A_VARIABLE_XMLCONTENT(v, prefix), + VARIABLE_FIELD(v, f), + A_FIELD_XMLCONTENT(f, suffix); + + HVAR_NAMEX(hv.clone(), format!("{}:{}:{}", fn_id, space, off)) <-- + hvar_hfunc(hv, fn_id), + A_HIGH_REPREF(hv, r), + A_ADDR_REF(a, r), + A_ADDR_OFFSET(a, off), + A_ADDR_SPACE(a, space), + location_hfunc(a, fn_id); + + HVAR_NAMEX(hv.clone(), format!("{}:{}", cls, off)) <-- + A_HIGH_CLASS(hv, cls), + E_HIGH_ADDR(hv, addr), + A_ADDR_OFFSET(addr, off); + + HVAR_REPRESENTATIVEX(hv.clone(), id.clone()) <-- + vnode_id(id, a), + A_ADDR_REF(a, r), + A_HIGH_REPREF(hv, r); + + HVAR_TYPEX(hv.clone(), t.clone()) <-- + E_HIGH_TYPE(hv, t); + + HVAR_TYPEX(hv.clone(), r.clone()) <-- + E_HIGH_TYPEREF(hv, r); + + + BB_FIRSTX(bb.clone(), op.clone()) <-- + E_BLOCK_OP(bb, op), + A_OP_INDEX(op, n), + if *n == 0; + + BB_EDGE(b0.clone(), b1.clone()) <-- + A_BLOCKEDGE_INDEX(be, to), + E_BLOCKEDGE_EDGE(be, e), + A_EDGE_END(e, from), + _BLOCK_INDEX(b0, from), + A_BLOCK_INDEX(b1, to); + + BB_HFUNCX(bb.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_BLOCK(f, bb); + + BB_HFUNCX(bb.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_AST(f, ast), + E_AST_BLOCK(ast, bb); + + BB_HFUNCX(bb.clone(), fn_id.clone()) <-- + BB_HFUNCX(bbf, fn_id), + E_BLOCK_BLOCK(bbf, bb); + + + HFUNC_EPX(fn_id.clone(), off.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_ADDR(f, addr), + A_ADDR_OFFSET(addr, off); + + HFUNC_LOCAL_EPX(off.clone(), off.clone()) <-- + E_FUNCTION_ADDR(_, addr), + A_ADDR_OFFSET(addr, off); + + HFUNC_FUNCX(fn_id.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, _); + + HFUNC_NAMEX(fn_id.clone(), name.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + A_FUNCTION_NAME(f, name); + + HFUNC_ISEXTX(fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + HFUNC_FUNCX(f, fx), + FUNC_ISEXT(fx); + + HFUNC_PROTOX(fn_id.clone(), p.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_FUNCPROTO(f, p); + + + PROTO_CALLING_CONVENTIONX(proto.clone(), cc.clone()) <-- + A_PROTOTYPE_MODEL(proto, cc); + + PROTO_HAS_THISX(proto.clone()) <-- + A_PROTOTYPE_MODEL(proto, &"__thiscall".to_string()); + + PROTO_IS_CONSTRUCTORX(proto.clone()) <-- + A_PROTOTYPE_CONSTRUCTOR(proto, &"true".to_string()); + + PROTO_IS_DESTRUCTORX(proto.clone()) <-- + A_PROTOTYPE_DESTRUCTOR(proto, &"true".to_string()); + + PROTO_IS_INLINEX(proto.clone()) <-- + A_PROTOTYPE_INLINE(proto, &"true".to_string()); + PROTO_IS_VARARGX(proto.clone()) <-- + A_PROTOTYPE_DOTDOTDOT(proto, &"true".to_string()); + + PROTO_IS_VOIDX(proto.clone()) <-- + E_PROTOTYPE_RETURNSYM(proto, ret), E_RETURNSYM_VOID(ret, _); + + PROTO_PARAMETERX(proto.clone(), *n, p.clone()) <-- + SYMBOL_HFUNCX(p, fn_id), + A_SYMBOL_CAT(p, &0), A + _SYMBOL_INDEX(p, n), + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_FUNCPROTO(f, proto); + + PROTO_PARAMETER_COUNTX(proto.clone(), mx + 1) <-- + agg mx = ascent::aggregators::max(n) <-- PROTO_PARAMETERX(proto, n, _); + + PROTO_PARAMETER_DATATYPEX(p.clone(), t.clone()) <-- + PROTO_PARAMETERX(_, , p), E_SYMBOL_TYPE(p, t); + + PROTO_PARAMETER_DATATYPEX(p.clone(), r.clone()) <-- + PROTO_PARAMETERX(, _, p), E_SYMBOL_TYPEREF(p, r); + + PROTO_RETTYPEX(proto.clone(), t.clone()) <-- + E_PROTOTYPE_RETURNSYM(proto, sym), E_RETURNSYM_TYPE(sym, t); + + PROTO_RETTYPEX(proto.clone(), r.clone()) <-- + E_PROTOTYPE_RETURNSYM(proto, sym), E_RETURNSYM_TYPEREF(sym, r); + + + varnode_hfunc(v.clone(), fn_id.clone()) <-- + E_BLOCK_VARIABLE(bb, v), + BB_HFUNCX(bb, fn_id); + + varnode_hfunc(v.clone(), fn_id.clone()) <-- + E_STATEMENT_VARIABLE(st, v), + E_BLOCK_STATEMENT(bb, st), + BB_HFUNCX(bb, fn_id); + + varnode_hfunc(v.clone(), fn_id.clone()) <-- + E_VARDECL_VARIABLE(decl, v), + E_FUNCTION_VARDECL(f, decl), + E_DOC_FUNCTION(fn_id, f); + + varnode_hfunc(v.clone(), fn_id.clone()) <-- + E_VARDECL_VARIABLE(decl, v), + E_FUNCPROTO_VARDECL(proto, decl), + E_FUNCTION_FUNCPROTO(f, proto), + E_DOC_FUNCTION(fn_id, f); + + varnode_hfunc(v.clone(), fn_id.clone()) <-- + E_DOC_FUNCTION(fn_id, f), + E_FUNCTION_AST(f, ast), + E_AST_VARNODES(ast, v); + + varnode_hfunc(a.clone(), fn_id.clone()) <-- + E_OP_INPUT(op, a), + E_OP_SEQNUM(op, sq), + location_hfunc(sq, fn_id); + + varnode_hfunc(a.clone(), fn_id.clone()) <-- + E_OP_OUTPUT(op, a), + E_OP_SEQNUM(op, sq), + location_hfunc(sq, fn_id); + + varnode_hvar(v.clone(), hv.clone()) <-- + E_HIGH_ADDR(hv, addr), + A_ADDR_REF(addr, r), + A_VARIABLE_VARREF(v, r), + location_hfunc(addr, fn_id), + varnode_hfunc(v, fn_id); + + varnode_hvar(v.clone(), hv.clone()) <-- + E_HIGH_ADDR(hv, addr), + A_HIGH_REPREF(hv, r), + A_VARIABLE_VARREF(v, r), + location_hfunc(addr, fn_id), + varnode_hfunc(v, fn_id); + + varnode_hvar(v.clone(), hv.clone()) <-- + A_VARIABLE_XMLCONTENT(v, _xml), + A_VARIABLE_OPREF(v, ref_val), + A_SEQNUM_UNIQ(sq, ref_val), + E_OP_SEQNUM(op, sq), + E_OP_ADDR(op, x), + A_ADDR_REF(x, xref), + A_HIGH_REPREF(hv, xref); +} + +// ========================================== +// 3. FACT IO UTILITY TRAITS +// ========================================== +trait WriteTsv { + fn write_tsv(&self, writer: &mut BufWriter) -> std::io::Result<()>; +} + +impl WriteTsv for () { + fn write_tsv(&self, writer: &mut BufWriter) -> + td::io::Result<()> { + writeln!(writer) + } +} + +impl WriteTsv for (T,) { + fn write_tsv(&self, writer: &mut BufWriter) -> + std::io::Result<()> { + writeln!(writer, "{}", self.0) + } +} + +impl WriteTsv for (T1, T2) { + fn write_tsv(&self, writer: &mut BufWriter) -> s + td::io::Result<()> { + writeln!(writer, "{}\t{}", self.0, self.1) + } +} + +impl WriteTsv for (T1, T2, T3) { + fn write_tsv(&self, writer: &mut BufWriter) -> + std::io::Result<()> { + writeln!(writer, "{}\t{}\t{}", self.0, self.1, self.2) + } +} + +fn export_relation(data: &[T], filename: &str) -> +std::io::Result<()> { + let base_dir = "./export"; + let path = Path::new(base_dir).join(filename); + let file = File::create(path)?; + let mut writer = BufWriter::new(file); + for row in data { + row.write_tsv(&mut writer)?; + } + Ok(()) +} + +// ========================================== +// 4. MAIN PROGRAM RUNTIME LOOP +// ========================================== +fn main() { + let mut prog = AscentProgram::default(); + println!("Starting Ascent PCode Engine Evaluation loop..."); + prog.run(); + println!("Evaluation complete. Serializing data to TSV targets..."); + + // Export output sequences mirroring Souffle target allocationslet _ = export_relation(&prog.tmp, "TMP.facts"); + let _ = export_relation(&prog.OFFSET_INDEXX, "OFFSET_INDEX.facts"); + let _ = export_relation(&prog.VNODE_SPACEX, "VNODE_SPACE.facts"); + let _ = export_relation(&prog.VNODE_PC_ADDRESSX, "VNODE_PC_ADDRESS.facts"); + let _ = export_relation(&prog.VNODE_ADDRESSX, "VNODE_ADDRESS.facts"); + let _ = export_relation(&prog.VNODE_OFFSETX, "VNODE_OFFSET.facts"); + let _ = export_relation(&prog.VNODE_OFFSET_NX, "VNODE_OFFSET_N.facts"); + let _ = export_relation(&prog.VNODE_NAMEX, "VNODE_NAME.facts"); + let _ = export_relation(&prog.VNODE_SIZEX, "VNODE_SIZE.facts"); + let _ = export_relation(&prog.VNODE_HFUNCX, "VNODE_HFUNC.facts"); + let _ = export_relation(&prog.VNODE_HVARX, "VNODE_HVAR.facts"); + let _ = export_relation(&prog.PCODE_INDEXX, "PCODE_INDEX.facts"); + let _ = export_relation(&prog.PCODE_INPUTX, "PCODE_INPUT.facts"); + let _ = export_relation(&prog.PCODE_OUTPUTX, "PCODE_OUTPUT.facts"); + let _ = export_relation(&prog.PCODE_MNEMONICX, "PCODE_MNEMONIC.facts"); + let _ = export_relation(&prog.PCODE_NEXTX, "PCODE_NEXT.facts"); + let _ = export_relation(&prog.PCODE_OPCODEX, "PCODE_OPCODE.facts"); + let _ = export_relation(&prog.PCODE_TARGETX, "PCODE_TARGET.facts"); + let _ = export_relation(&prog.PCODE_PARENTX, "PCODE_PARENT.facts"); + let _ = export_relation(&prog.SYMBOL_NAMEX, "SYMBOL_NAME.facts"); + let _ = export_relation(&prog.SYMBOL_HFUNCX, "SYMBOL_HFUNC.facts"); + let _ = export_relation(&prog.SYMBOL_HVARX, "SYMBOL_HVAR.facts"); + let _ = export_relation(&prog.hvar_hfunc, "HVAR_HFUNC.facts"); + let _ = export_relation(&prog.HVAR_NAMEX, "HVAR_NAME.facts"); + let _ = export_relation(&prog.HVAR_REPRESENTATIVEX, "HVAR_REPRESENTATIVE.facts"); + let _ = export_relation(&prog.HFUNC_EPX, "HFUNC_EP.facts"); + let _ = export_relation(&prog.HFUNC_FUNCX, "HFUNC_FUNC.facts"); + let _ = export_relation(&prog.HFUNC_NAMEX, "HFUNC_NAME.facts"); + let _ = export_relation(&prog.HFUNC_ISEXTX, "HFUNC_ISEXT.facts"); + let _ = export_relation(&prog.HFUNC_LOCAL_EPX, "HFUNC_LOCAL_EP.facts"); + let _ = export_relation(&prog.HFUNC_PROTOX, "HFUNC_PROTO.facts"); + let _ = export_relation(&prog.BB_FIRSTX, "BB_FIRST.facts"); + let _ = export_relation(&prog.BB_HFUNCX, "BB_HFUNC.facts"); + let _ = export_relation(&prog.pcode_id, "PCODE_ID.facts"); + let _ = export_relation(&prog.vnode_id, "VNODE_ID.facts"); + let _ = export_relation(&prog.location_hfunc, "LOCATION_HFUNC.facts"); + let _ = export_relation(&prog.varnode_hfunc, "VARNODE_HFUNC.facts"); + let _ = export_relation(&prog.varnode_hvar, "VARNODE_HVAR.facts"); + println!("All data successfully written out to the export directory!"); +} diff --git a/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang_ext.dl b/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang_ext.dl new file mode 100644 index 0000000000..d3584cfd7a --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/data/ctadl/pcode_lang_ext.dl @@ -0,0 +1,489 @@ +// This file will eventually be incorporate upstream in the CTADL project. +// It resides here purely to facilitate coordination. + +#include "pcode/declarations_ext.dl" + +location_hfunc(a, fn) :- + LOCATION_FUNC(a, fn). + +op_hfunc(op, fn), +bb_hfunc(bb, fn), +location_hfunc(a, fn) :- + (E_OP_ADDR(op, a) ; E_OP_IOP(op, a)), + E_BLOCK_OP(bb, op), + BB_HFUNCX(bb, fn), + E_DOC_FUNCTION(fn, _). + +OFFSET_INDEXX(num, n) :- + LOCATION_NUM(off, num), + LOCATION_UNIQ(off, n). + +// VNODE + +// vnode's either have refs, are constant (spaceid / iop), or are void +VNODE_NAMEX(id, vn), +vnode_id(id, a) :- + A_ADDR_REF(a, ref), + location_hfunc(a, fn), + vn = cat("vn", to_string(ref)), + id = cat(fn, ":", to_string(ref)). +// Tempted to add this, but the results are bad +// (E_OP_INPUT(_, a) ; E_OP_OUTPUT(_, a)), + +// checked +VNODE_SPACEX(id, "const"), +VNODE_ADDRESSX(id, num), +VNODE_NAMEX(id, id), +vnode_id(id, id) :- + E_OP_IOP(op, id), + A_IOP_VALUE(id, num). + +// checked +VNODE_SPACEX(id, "const"), +VNODE_ADDRESSX(id, num), +VNODE_NAMEX(id, id), +vnode_id(id, id) :- + E_OP_SPACEID(op, id), + A_SPACEID_NAME(id, num). + + +VNODE_ADDRESSX(id, num) :- + vnode_id(id, a), + A_ADDR_OFFSET(a, off), + LOCATION_NUM(off, num). + +VNODE_SPACEX(id, sp) :- + vnode_id(id, a), + A_ADDR_SPACE(a, sp). + +VNODE_OFFSETX(id, off) :- + VNODE_ADDRESSX(id, a), + LOCATION_HEX(a, off). + +VNODE_OFFSET_NX(id, n) :- + VNODE_ADDRESSX(id, a), + LOCATION_NUM(a, n). + +VNODE_PC_ADDRESSX(id, off) :- + vnode_id(id, a), + A_ADDR_REF(a, aref), + A_VARIABLE_VARREF(v, aref), + A_VARIABLE_OPREF(v, ref), + A_SEQNUM_UNIQ(sq, ref), + A_SEQNUM_OFFSET(sq, off). + +VNODE_PC_ADDRESSX(id, off) :- + vnode_id(id, a), + E_OP_OUTPUT(op, a), + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, off). + + +VNODE_SIZEX(id, sz) :- + vnode_id(id, a), + A_ADDR_SIZE(a, sz). + +VNODE_SIZEX(id, sz) :- + vnode_id(id, a), + A_ADDR_REF(a, ref), + A_HIGH_REPREF(hv, ref), + E_HIGH_TYPE(hv, type), + A_TYPE_SIZE(type, sz). + + +VNODE_HFUNCX(id, fn) :- + vnode_id(id, a), + location_hfunc(a, fn). + +VNODE_HVARX(id, hv) :- + vnode_id(id, a), + E_HIGH_ADDR(hv, a). + +// PCODE + +PCODE_MNEMONICX(op, mn) :- + A_OP_CODE(op, n), + MNEMONICS(n, mn). + +PCODE_OPCODEX(op, n) :- + A_OP_CODE(op, n). + +PCODE_INPUTX(op, n, id) :- + E_OP_INPUT(op, addr), + vnode_id(id, addr), + A_INPUT_INDEX(addr, n). + +PCODE_OUTPUTX(op, id) :- + E_OP_OUTPUT(op, addr), + vnode_id(id, addr). + + +PCODE_TARGETX(op, addr) :- + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, addr). + +PCODE_PARENTX(op, p) :- + A_OP_CODE(op, _), + E_BLOCK_OP(p, op). + +PCODE_NEXTX(op, nxt) :- + E_OP_SEQNUM(op, opsq), + E_BLOCK_OP(block, op), + E_BLOCK_OP(block, nxt), + A_OP_INDEX(op, opn), + A_OP_INDEX(nxt, nxtn), + nxtn = opn + 1. + +pcode_id(op, var) :- + E_OP_SEQNUM(op, sq), + A_SEQNUM_OFFSET(sq, addr), + A_OP_INDEX(op, ref), + var = cat(addr, ":", to_string(ref)). + +PCODE_INDEXX(op, idx) :- + A_OP_INDEX(op, idx). + +// SYMBOL + +SYMBOL_NAMEX(hs, name) :- + A_SYMBOL_NAME(hs, name). + +// checked +SYMBOL_HVARX(hs, hv) :- + A_HIGH_SYMREF(hv, ref), + A_SYMBOL_ID(hs, ref), + hvar_hfunc(hv, fn), + SYMBOL_HFUNCX(hs, fn). + +// checked +SYMBOL_HFUNCX(hs, fn) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_LOCALDB(f, db), + E_LOCALDB_SCOPE(db, scope), + E_SCOPE_SYMBOLLIST(scope, list), + E_SYMBOLLIST_MAPSYM(list, map), + E_MAPSYM_SYMBOL(map, hs). + +// HVAR + +// test +hvar_hfunc(hv, fn) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_HIGHLIST(f, list), + E_HIGHLIST_HIGH(list, hv). + + +// checked +HVAR_NAMEX(hv, name) :- + SYMBOL_HVARX(sym, hv), + A_SYMBOL_NAME(sym, name). + +// adds for XML content +HVAR_NAMEX(hv, name) :- + varnode_hvar(v, hv), + A_VARIABLE_XMLCONTENT(v, name). + +HVAR_NAMEX(hv, name) :- + varnode_hvar(v, hv), + A_VARIABLE_XMLCONTENT(v, prefix), + VARIABLE_FIELD(v, f), + A_FIELD_XMLCONTENT(f, suffix), + name = cat(prefix, ".", suffix). + +// adds for addresses +HVAR_NAMEX(hv, name) :- + hvar_hfunc(hv, fn), + A_HIGH_REPREF(hv, ref), + A_ADDR_REF(a, ref), + A_ADDR_OFFSET(a, off), + A_ADDR_SPACE(a, space), + location_hfunc(a, fn), + name = cat(fn, ":", space, ":", to_string(off)). + +HVAR_NAMEX(hv, name) :- + A_HIGH_CLASS(hv, cls), + E_HIGH_ADDR(hv, addr), + A_ADDR_OFFSET(addr, off), + name = cat(cls, ":", to_string(off)). + +HVAR_REPRESENTATIVEX(hv, id) :- + vnode_id(id, a), + A_ADDR_REF(a, ref), + A_HIGH_REPREF(hv, ref). + +HVAR_TYPEX(hv, type) :- + E_HIGH_TYPE(hv, type). + +HVAR_TYPEX(hv, ref) :- + E_HIGH_TYPEREF(hv, ref). + +// BB + +BB_FIRSTX(bb, op) :- + E_BLOCK_OP(bb, op), + A_OP_INDEX(op, n), + n = 0. + +BB_EDGE(b0, b1) :- + A_BLOCKEDGE_INDEX(be, to), + E_BLOCKEDGE_EDGE(be, e), + A_EDGE_END(e, from), + A_BLOCK_INDEX(b0, from), + A_BLOCK_INDEX(b1, to). + +BB_HFUNCX(bb, fn) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_BLOCK(f, bb). + +BB_HFUNCX(bb, fn) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_AST(f, ast), + E_AST_BLOCK(ast, bb). + +BB_HFUNCX(bb, fn) :- + BB_HFUNCX(bbf, fn), + E_BLOCK_BLOCK(bbf, bb). + +// HFUNC + +HFUNC_EPX(fn, off) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_ADDR(f, addr), + A_ADDR_OFFSET(addr, off). + +HFUNC_LOCAL_EPX(off, off) :- + E_FUNCTION_ADDR(_, addr), + A_ADDR_OFFSET(addr, off). + +HFUNC_FUNCX(fn, fn) :- + E_DOC_FUNCTION(fn, _). + +HFUNC_NAMEX(fn, name) :- + E_DOC_FUNCTION(fn, f), + A_FUNCTION_NAME(f, name). + +HFUNC_ISEXTX(fn) :- + E_DOC_FUNCTION(fn, f), + HFUNC_FUNCX(f, fx), + FUNC_ISEXT(fx). + +HFUNC_PROTOX(fn, p) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_FUNCPROTO(f, p). + +// PROTO + +PROTO_CALLING_CONVENTIONX(proto, cc) :- + A_PROTOTYPE_MODEL(proto, cc). + +PROTO_HAS_THISX(proto) :- + A_PROTOTYPE_MODEL(proto, "__thiscall"). + +PROTO_IS_CONSTRUCTORX(proto) :- + A_PROTOTYPE_CONSTRUCTOR(proto, "true"). + +PROTO_IS_DESTRUCTORX(proto) :- + A_PROTOTYPE_DESTRUCTOR(proto, "true"). + +PROTO_IS_INLINEX(proto) :- + A_PROTOTYPE_INLINE(proto, "true"). + +PROTO_IS_VARARGX(proto) :- + A_PROTOTYPE_DOTDOTDOT(proto, "true"). + +PROTO_IS_VOIDX(proto) :- + E_PROTOTYPE_RETURNSYM(proto, ret), + E_RETURNSYM_VOID(ret, _). + +PROTO_PARAMETERX(proto, n, p) :- + SYMBOL_HFUNCX(p, fn), + A_SYMBOL_CAT(p, 0), + A_SYMBOL_INDEX(p, n), + E_DOC_FUNCTION(fn, f), + E_FUNCTION_FUNCPROTO(f, proto). + +PROTO_PARAMETER_COUNTX(proto, mx) :- + mx = 1 + max n : { + PROTO_PARAMETERX(proto, n, _) + }. + +PROTO_PARAMETER_DATATYPEX(p, type) :- + PROTO_PARAMETERX(_, _, p), + E_SYMBOL_TYPE(p, type). +// E_TYPE_TYPEREF(type, ref), +// A_TYPEREF_NAME(ref, name). + +PROTO_PARAMETER_DATATYPEX(p, ref) :- + PROTO_PARAMETERX(_, _, p), + E_SYMBOL_TYPEREF(p, ref). +// A_TYPEREF_NAME(ref, name). + +PROTO_RETTYPEX(proto, type) :- + E_PROTOTYPE_RETURNSYM(proto, sym), + E_RETURNSYM_TYPE(sym, type). +// A_TYPEREF_NAME(ref, name). + +PROTO_RETTYPEX(proto, ref) :- + E_PROTOTYPE_RETURNSYM(proto, sym), + E_RETURNSYM_TYPEREF(sym, ref). +// A_TYPEREF_NAME(ref, name). + +// Helper relations: VARNODE_... + +varnode_hfunc(v, fn) :- + E_BLOCK_VARIABLE(bb, v), + BB_HFUNCX(bb, fn). + +varnode_hfunc(v, fn) :- + E_STATEMENT_VARIABLE(st, v), + E_BLOCK_STATEMENT(bb, st), + BB_HFUNCX(bb, fn). + +varnode_hfunc(v, fn) :- + E_VARDECL_VARIABLE(decl, v), + E_FUNCTION_VARDECL(f, decl), + E_DOC_FUNCTION(fn, f). + +varnode_hfunc(v, fn) :- + E_VARDECL_VARIABLE(decl, v), + E_FUNCPROTO_VARDECL(proto, decl), + E_FUNCTION_FUNCPROTO(f, proto), + E_DOC_FUNCTION(fn, f). + +varnode_hfunc(v, fn) :- + E_DOC_FUNCTION(fn, f), + E_FUNCTION_AST(f, ast), + E_AST_VARNODES(ast, v). + +varnode_hfunc(a, fn) :- + (E_OP_INPUT(op, a) ; E_OP_OUTPUT(op, a)), + E_OP_SEQNUM(op, sq), + location_hfunc(sq, fn). + + +varnode_hvar(v, hv) :- + E_HIGH_ADDR(hv, addr), + A_ADDR_REF(addr, ref), + A_VARIABLE_VARREF(v, ref), + location_hfunc(addr, fn), + varnode_hfunc(v, fn). + +varnode_hvar(v, hv) :- + E_HIGH_ADDR(hv, addr), + A_HIGH_REPREF(hv, ref), + A_VARIABLE_VARREF(v, ref), + location_hfunc(addr, fn), + varnode_hfunc(v, fn). + +// Should this be E_OP_OUTPUT? +varnode_hvar(v, hv) :- + A_VARIABLE_XMLCONTENT(v, _), + A_VARIABLE_OPREF(v, ref), + A_SEQNUM_UNIQ(sq, ref), + E_OP_SEQNUM(op, sq), + E_OP_ADDR(op, x), + A_ADDR_REF(x, xref), + A_HIGH_REPREF(hv, xref). + + +.output OFFSET_INDEXX(IO=file, filename="./export/OFFSET_INDEX.facts") +.output VNODE_SPACEX(IO=file, filename="./export/VNODE_SPACE.facts") +.output VNODE_PC_ADDRESSX(IO=file, filename="./export/VNODE_PC_ADDRESS.facts") +.output VNODE_ADDRESSX(IO=file, filename="./export/VNODE_ADDRESS.facts") +.output VNODE_OFFSETX(IO=file, filename="./export/VNODE_OFFSET.facts") +.output VNODE_OFFSET_NX(IO=file, filename="./export/VNODE_OFFSET_N.facts") +.output VNODE_NAMEX(IO=file, filename="./export/VNODE_NAME.facts") +.output VNODE_SIZEX(IO=file, filename="./export/VNODE_SIZE.facts") +.output VNODE_HFUNCX(IO=file, filename="./export/VNODE_HFUNC.facts") +.output VNODE_HVARX(IO=file, filename="./export/VNODE_HVAR.facts") +.output PCODE_INDEXX(IO=file, filename="./export/PCODE_INDEX.facts") +.output PCODE_INPUTX(IO=file, filename="./export/PCODE_INPUT.facts") +.output PCODE_OUTPUTX(IO=file, filename="./export/PCODE_OUTPUT.facts") +.output PCODE_MNEMONICX(IO=file, filename="./export/PCODE_MNEMONIC.facts") +.output PCODE_NEXTX(IO=file, filename="./export/PCODE_NEXT.facts") +.output PCODE_OPCODEX(IO=file, filename="./export/PCODE_OPCODE.facts") +.output PCODE_TARGETX(IO=file, filename="./export/PCODE_TARGET.facts") +.output PCODE_PARENTX(IO=file, filename="./export/PCODE_PARENT.facts") +.output SYMBOL_NAMEX(IO=file, filename="./export/SYMBOL_NAME.facts") +.output SYMBOL_HFUNCX(IO=file, filename="./export/SYMBOL_HFUNC.facts") +.output SYMBOL_HVARX(IO=file, filename="./export/SYMBOL_HVAR.facts") +.output hvar_hfunc(IO=file, filename="./export/HVAR_HFUNC.facts") +.output HVAR_NAMEX(IO=file, filename="./export/HVAR_NAME.facts") +.output HVAR_REPRESENTATIVEX(IO=file, filename="./export/HVAR_REPRESENTATIVE.facts") +.output HFUNC_EPX(IO=file, filename="./export/HFUNC_EP.facts") +.output HFUNC_FUNCX(IO=file, filename="./export/HFUNC_FUNC.facts") +.output HFUNC_NAMEX(IO=file, filename="./export/HFUNC_NAME.facts") +.output HFUNC_ISEXTX(IO=file, filename="./export/HFUNC_ISEXT.facts") +.output HFUNC_LOCAL_EPX(IO=file, filename="./export/HFUNC_LOCAL_EP.facts") +.output HFUNC_PROTOX(IO=file, filename="./export/HFUNC_PROTO.facts") +.output BB_FIRSTX(IO=file, filename="./export/BB_FIRST.facts") +.output BB_HFUNCX(IO=file, filename="./export/BB_HFUNC.facts") +.output PROTO_CALLING_CONVENTIONX(IO=file, filename="./export/PROTO_CALLING_CONVENTION.facts") +.output PROTO_IS_VOIDX(IO=file, filename="./export/PROTO_IS_VOID.facts") +.output PROTO_IS_VARARGX(IO=file, filename="./export/PROTO_IS_VARARG.facts") +.output PROTO_IS_INLINEX(IO=file, filename="./export/PROTO_IS_INLINE.facts") +.output PROTO_IS_CONSTRUCTORX(IO=file, filename="./export/PROTO_IS_CONSTRUCTOR.facts") +.output PROTO_IS_DESTRUCTORX(IO=file, filename="./export/PROTO_IS_DESTRUCTOR.facts") +.output PROTO_HAS_THISX(IO=file, filename="./export/PROTO_HAS_THIS.facts") +.output PROTO_PARAMETERX(IO=file, filename="./export/PROTO_PARAMETER.facts") +.output PROTO_PARAMETER_COUNTX(IO=file, filename="./export/PROTO_PARAMETER_COUNT.facts") +.output PROTO_PARAMETER_DATATYPEX(IO=file, filename="./export/PROTO_PARAMETER_DATATYPE.facts") +.output PROTO_RETTYPEX(IO=file, filename="./export/PROTO_RETTYPE.facts") + +.output pcode_id(IO=file, filename="./export/PCODE_ID.facts") +.output vnode_id(IO=file, filename="./export/VNODE_ID.facts") +.output location_hfunc(IO=file, filename="./export/LOCATION_HFUNC.facts") +.output varnode_hfunc(IO=file, filename="./export/VARNODE_HFUNC.facts") +.output varnode_hvar(IO=file, filename="./export/VARNODE_HVAR.facts") + +.output VNODE_SPACEX(CTADL_OUTPUT_DB_IO) +.output VNODE_PC_ADDRESSX(CTADL_OUTPUT_DB_IO) +.output VNODE_ADDRESSX(CTADL_OUTPUT_DB_IO) +.output VNODE_SIZEX(CTADL_OUTPUT_DB_IO) +.output VNODE_HFUNCX(CTADL_OUTPUT_DB_IO) +.output VNODE_HVARX(CTADL_OUTPUT_DB_IO) +.output VNODE_OFFSETX(CTADL_OUTPUT_DB_IO) +.output VNODE_OFFSET_NX(CTADL_OUTPUT_DB_IO) +.output VNODE_NAMEX(CTADL_OUTPUT_DB_IO) +.output OFFSET_INDEXX(CTADL_OUTPUT_DB_IO) +.output PCODE_MNEMONICX(CTADL_OUTPUT_DB_IO) +.output PCODE_INDEXX(CTADL_OUTPUT_DB_IO) +.output PCODE_INPUTX(CTADL_OUTPUT_DB_IO) +.output PCODE_OUTPUTX(CTADL_OUTPUT_DB_IO) +.output PCODE_NEXTX(CTADL_OUTPUT_DB_IO) +.output PCODE_OPCODEX(CTADL_OUTPUT_DB_IO) +.output PCODE_TARGETX(CTADL_OUTPUT_DB_IO) +.output PCODE_PARENTX(CTADL_OUTPUT_DB_IO) +.output PCODE_NEXTX(CTADL_OUTPUT_DB_IO) +.output SYMBOL_NAMEX(CTADL_OUTPUT_DB_IO) +.output SYMBOL_HVARX(CTADL_OUTPUT_DB_IO) +.output SYMBOL_HFUNCX(CTADL_OUTPUT_DB_IO) +.output HVAR_NAMEX(CTADL_OUTPUT_DB_IO) +.output HVAR_REPRESENTATIVEX(CTADL_OUTPUT_DB_IO) +.output HVAR_TYPEX(CTADL_OUTPUT_DB_IO) +.output BB_FIRSTX(CTADL_OUTPUT_DB_IO) +.output BB_HFUNCX(CTADL_OUTPUT_DB_IO) +.output HFUNC_ISEXTX(CTADL_OUTPUT_DB_IO) +.output HFUNC_EPX(CTADL_OUTPUT_DB_IO) +.output HFUNC_FUNCX(CTADL_OUTPUT_DB_IO) +.output HFUNC_NAMEX(CTADL_OUTPUT_DB_IO) +.output HFUNC_LOCAL_EPX(CTADL_OUTPUT_DB_IO) +.output HFUNC_PROTOX(CTADL_OUTPUT_DB_IO) +.output PROTO_CALLING_CONVENTIONX(CTADL_OUTPUT_DB_IO) +.output PROTO_IS_VOIDX(CTADL_OUTPUT_DB_IO) +.output PROTO_IS_VARARGX(CTADL_OUTPUT_DB_IO) +.output PROTO_IS_INLINEX(CTADL_OUTPUT_DB_IO) +.output PROTO_IS_CONSTRUCTORX(CTADL_OUTPUT_DB_IO) +.output PROTO_IS_DESTRUCTORX(CTADL_OUTPUT_DB_IO) +.output PROTO_HAS_THISX(CTADL_OUTPUT_DB_IO) +.output PROTO_PARAMETERX(CTADL_OUTPUT_DB_IO) +.output PROTO_PARAMETER_COUNTX(CTADL_OUTPUT_DB_IO) +.output PROTO_PARAMETER_DATATYPEX(CTADL_OUTPUT_DB_IO) +.output PROTO_RETTYPEX(CTADL_OUTPUT_DB_IO) + +.output pcode_id(CTADL_OUTPUT_DB_IO) +.output vnode_id(CTADL_OUTPUT_DB_IO) +.output location_hfunc(CTADL_OUTPUT_DB_IO) + + + diff --git a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportFunctionPcodeViaDecoderScript.java b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportFunctionPcodeViaDecoderScript.java new file mode 100644 index 0000000000..b70ffa3827 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportFunctionPcodeViaDecoderScript.java @@ -0,0 +1,61 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//Decompile the function at the cursor and its callees, then output facts files corresponding to the pcodes +//@category PCode + +import java.io.File; + +import ghidra.app.plugin.core.decompiler.export.ExportDecompilationTask; +import ghidra.app.script.GhidraScript; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionManager; +import ghidra.util.task.TaskLauncher; + +public class ExportFunctionPcodeViaDecoderScript extends GhidraScript { + + File outputDirectory; + + @Override + protected void run() throws Exception { + + String[] args = getScriptArgs(); + PluginTool tool = state.getTool(); + if (tool == null) { + println("Script is not running in GUI"); + } + if (args.length >= 1) { + outputDirectory = new File(args[0]); + } + else { + outputDirectory = askDirectory("Select Directory for Results", "OK"); + } + + long startTime = System.nanoTime(); + + FunctionManager functionManager = currentProgram.getFunctionManager(); + Function currentFunction = functionManager.getFunctionContaining(currentAddress); + ExportDecompilationTask task = + new ExportDecompilationTask("Export Pcode", currentProgram, currentFunction, + outputDirectory); + TaskLauncher.launch(task); + + long endTime = System.nanoTime(); + long duration = (endTime - startTime) / 1000000; + println("total duration: " + Long.toString(duration)); + } + +} diff --git a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForCTADL.java b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForCTADL.java index ca831332cd..eb7fac5390 100644 --- a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForCTADL.java +++ b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForCTADL.java @@ -17,7 +17,6 @@ //@category PCode import java.io.*; -import java.lang.Enum; import java.math.BigInteger; import java.util.*; import java.util.concurrent.*; @@ -33,6 +32,7 @@ import ghidra.program.database.symbol.FunctionSymbol; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.data.*; +import ghidra.program.model.data.Enum; import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.*; diff --git a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPcodeViaDecoderScript.java b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPcodeViaDecoderScript.java new file mode 100644 index 0000000000..6ba3af927c --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPcodeViaDecoderScript.java @@ -0,0 +1,56 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//Decompile the current program's functions, then output facts files corresponding to the pcodes +//@category PCode + +import java.io.File; + +import ghidra.app.plugin.core.decompiler.export.ExportDecompilationTask; +import ghidra.app.script.GhidraScript; +import ghidra.framework.plugintool.PluginTool; +import ghidra.util.task.TaskLauncher; + +public class ExportPcodeViaDecoderScript extends GhidraScript { + + File outputDirectory; + + @Override + protected void run() throws Exception { + + String[] args = getScriptArgs(); + PluginTool tool = state.getTool(); + if (tool == null) { + println("Script is not running in GUI"); + } + if (args.length >= 1) { + outputDirectory = new File(args[0]); + } + else { + outputDirectory = askDirectory("Select Directory for Results", "OK"); + } + + long startTime = System.nanoTime(); + + ExportDecompilationTask task = + new ExportDecompilationTask("Export Pcode", currentProgram, outputDirectory); + TaskLauncher.launch(task); + + long endTime = System.nanoTime(); + long duration = (endTime - startTime) / 1000000; + println("total duration: " + Long.toString(duration)); + } + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/BasePcodeExporter.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/BasePcodeExporter.java new file mode 100644 index 0000000000..e510a2ccc6 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/BasePcodeExporter.java @@ -0,0 +1,62 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.io.*; + +public class BasePcodeExporter { + + protected final PcodeDatabase db = new PcodeDatabase(); + protected final Writer debug; + protected final String directory; + + final static char SEP = ':'; + final static char TAB = '\t'; + final static char QUOTE = '\"'; + + public BasePcodeExporter(String directory) throws IOException { + this.directory = directory; + debug = new BufferedWriter(new FileWriter(new File(directory, "PcodeOps.facts"))); + } + + public void writeFacts(boolean writeAll) { + db.writeFacts(directory, writeAll); + } + + public void writeDebug() throws IOException { + debug.close(); + } + + public PcodeDatabase getDatabase() { + return db; + } + + void export(String pfile, String key, String value) { + db.addExport(pfile, key, value); + } + + + protected void debug(String s) { + try { + this.debug.write(s); + this.debug.write('\n'); + } + catch (IOException e) { + throw new RuntimeException(e.toString()); + } + db.addExport("PcodeOps", s); + } +} diff --git a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForSingleFunction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/DecoderMethods.java similarity index 55% rename from Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForSingleFunction.java rename to Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/DecoderMethods.java index 00a8ebf2b4..6f7757e609 100644 --- a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportPCodeForSingleFunction.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/DecoderMethods.java @@ -4,29 +4,30 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ -//Decompile the function at the cursor and its callees, then output facts files corresponding to the pcodes -//@category PCode +package ghidra.app.plugin.core.decompiler.export; -import java.util.HashSet; -import java.util.Set; +/** + * Describes the per-data-type methods for reading for XML attributes and elements via the decoder + */ -import ghidra.program.model.listing.Function; +public enum DecoderMethods { -public class ExportPCodeForSingleFunction extends ExportPCodeForCTADL { + READ_BOOL, + READ_SINT, + READ_UINT, + READ_STRING, + READ_SPACE, + READ_OPCODE, - protected Set getFunctionSet() { - Set toProcess = new HashSet(); - toProcess.add(getFunctionContaining(currentAddress)); - return toProcess; - } + READ_UNKNOWN; } diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompInterface.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompInterface.java new file mode 100644 index 0000000000..261f57836d --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompInterface.java @@ -0,0 +1,83 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileProcess; +import ghidra.program.model.address.Address; +import ghidra.program.model.lang.Language; +import ghidra.program.model.listing.Function; +import ghidra.program.model.pcode.*; +import ghidra.program.model.symbol.IdentityNameTransformer; +import ghidra.program.model.symbol.NameTransformer; +import ghidra.util.task.TaskMonitor; + +public class ExportDecompInterface extends DecompInterface { + + @Override + public synchronized ExportableDecompileResults decompileFunction(Function func, int timeoutSecs, + TaskMonitor monitor) { + + Language pcodelanguage = getLanguage(); + NameTransformer transformer = + (getOptions() == null) ? new IdentityNameTransformer() + : getOptions().getNameTransformer(); + PcodeDataTypeManager dtmgr = new PcodeDataTypeManager(func.getProgram(), transformer); + dtmgr.clearTemporaryIds(); + errorMessage = ""; + + if (monitor != null) { + monitor.addCancelledListener(monitorListener); + } + + PackedDecode decoder = null; + try { + Address funcEntry = func.getEntryPoint(); + decompCallback.setFunction(func, funcEntry, null); + EncodeDecodeSet activeSet = setupEncodeDecode(funcEntry); + decoder = activeSet.mainResponse; + verifyProcess(); + activeSet.mainQuery.clear(); + AddressXML.encode(activeSet.mainQuery, funcEntry); + decompProcess.sendCommandTimeout("decompileAt", timeoutSecs, activeSet); + errorMessage = decompCallback.getErrorMessage(); + } + catch (Exception ex) { + decoder.clear(); // Clear any partial result + errorMessage = "Exception while decompiling " + func.getEntryPoint() + ": " + + ex.getMessage() + '\n'; + } + finally { + if (monitor != null) { + monitor.removeCancelledListener(monitorListener); + } + } + + DecompileProcess.DisposeState processState; + if (decompProcess != null) { + processState = decompProcess.getDisposeState(); + if (decompProcess.getDisposeState() == DecompileProcess.DisposeState.NOT_DISPOSED) { + flushCache(); + } + } + else { + processState = DecompileProcess.DisposeState.DISPOSED_ON_CANCEL; + } + + return new ExportableDecompileResults(func, pcodelanguage, compilerSpec, dtmgr, + errorMessage, decoder, processState); + } +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilationTask.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilationTask.java new file mode 100644 index 0000000000..d592b2dee3 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilationTask.java @@ -0,0 +1,158 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import ghidra.app.decompiler.DecompileResults; +import ghidra.app.decompiler.parallel.DecompilerCallback; +import ghidra.app.decompiler.parallel.ParallelDecompiler; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.Program; +import ghidra.util.Msg; +import ghidra.util.exception.CancelledException; +import ghidra.util.task.Task; +import ghidra.util.task.TaskMonitor; + +public class ExportDecompilationTask extends Task { + + private final Program currentProgram; + private final Function currentFunction; + private final File outputDirectory; + + public ExportDecompilationTask(String title, Program program, File outputDirectory) { + super(title); + this.currentProgram = program; + this.currentFunction = null; + this.outputDirectory = outputDirectory; + } + + public ExportDecompilationTask(String title, Program program, Function function, + File outputDirectory) { + super(title); + this.currentProgram = program; + this.currentFunction = function; + this.outputDirectory = outputDirectory; + } + + @Override + public void run(TaskMonitor monitor) throws CancelledException { + PcodeExporter ex; + try { + ex = new PcodeExporter(outputDirectory.getAbsolutePath()); + } + catch (IOException e) { + Msg.error(this, e.getMessage()); + return; + } + //ex.getDatabase().addExport(ex.LANGUAGE, "PCODE"); + ex.getDatabase().addExport(ex.PROGRAM_FILE, currentProgram.toString()); + + ExportDecompilerConfigurer configurer = new ExportDecompilerConfigurer(); + + DecompilerCallback callback = + new DecompilerCallback<>(currentProgram, configurer) { + + // This could be done better, when results are available, other decompiler + // results will stall. + @Override + public synchronized ExportableDecompileResults process(DecompileResults results, + TaskMonitor tMonitor) throws Exception { + ExportableDecompileResults rx = (ExportableDecompileResults) results; + rx.processDoc(ex); + return rx; + } + + @Override + public ExportableDecompileResults process(Function f, TaskMonitor monitor) + throws Exception { + if (monitor.isCancelled()) { + return null; + } + + ExportDecompInterface decompiler = new ExportDecompInterface(); + configurer.configure(decompiler); + decompiler.openProgram(f.getProgram()); + ExportableDecompileResults decompileResults; + + monitor.setMessage("Decompiling " + f.getName()); + decompileResults = decompiler.decompileFunction(f, 10, monitor); + + ExportableDecompileResults r = process(decompileResults, monitor); + return r; + + } + + }; + + Set toProcess = new HashSet(); + if (currentFunction != null) { + toProcess.add(currentFunction); + } + else { + currentProgram.getFunctionManager().getFunctions(true).forEach(f -> { + toProcess.add(f); + }); + //currentProgram.getFunctionManager().getExternalFunctions().forEach(f -> { + // toProcess.add(f); + //}); + } + + List toProcessList = new ArrayList<>(toProcess); + Collections.sort(toProcessList, + Comparator. comparingLong(f -> f.getBody().getNumAddresses()).reversed()); + + monitor.initialize(toProcess.size()); + + // dump defined data once + ex.exportDefinedData(currentProgram); + ex.exportRegisterInfo(currentProgram); + ex.exportAddressSpaces(currentProgram); + ex.exportMnemonics(currentProgram); + + try { + ParallelDecompiler.decompileFunctions(callback, toProcessList, monitor); + } + catch (InterruptedException e) { + throw new CancelledException(); + } + catch (Exception e) { + Msg.error(this, e.getMessage()); + return; + } + + // System.out.println("Done producing"); + + ex.externalFunctionParameters(currentProgram); + ex.processVTables(currentProgram); + // waiting until the end to write all datatypes TYPE_ may not save much time. + // It could save time if the structures are complicated, so constantly + // traversing + // structure references all over again every 50 functions. Might not be worth + // it. + try { + ex.writeFacts(true); + ex.writeDebug(); + } + catch (IOException e) { + Msg.error(this, e.getMessage()); + return; + } + } + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilerConfigurer.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilerConfigurer.java new file mode 100644 index 0000000000..43138b6521 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportDecompilerConfigurer.java @@ -0,0 +1,37 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileOptions; +import ghidra.app.decompiler.parallel.DecompileConfigurer; + +public class ExportDecompilerConfigurer implements DecompileConfigurer { + + final ExportDecompInterface ifc = new ExportDecompInterface(); + + @Override + public void configure(DecompInterface decompiler) { + decompiler.setOptions(new DecompileOptions()); + // can also use "normalize" but that won't generate HighVariables + decompiler.setSimplificationStyle("decompile"); + } + + ExportDecompInterface getInterface() { + return ifc; + } + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportableDecompileResults.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportableDecompileResults.java new file mode 100644 index 0000000000..420f69b945 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/ExportableDecompileResults.java @@ -0,0 +1,211 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import static ghidra.program.model.pcode.ElementId.*; + +import java.util.HashSet; +import java.util.Set; + +import ghidra.app.decompiler.DecompileProcess; +import ghidra.app.decompiler.DecompileResults; +import ghidra.program.model.lang.CompilerSpec; +import ghidra.program.model.lang.Language; +import ghidra.program.model.listing.Function; +import ghidra.program.model.pcode.*; +import ghidra.util.Msg; + +public class ExportableDecompileResults extends DecompileResults { + + final PackedDecode localDecoder; + final private Set valueSet = new HashSet<>(); + + private BasePcodeExporter ex; + private int addressUnique = 0; + + public ExportableDecompileResults(Function func, Language language, CompilerSpec compilerSpec, + PcodeDataTypeManager dtm, String errorMsg, PackedDecode decoder, + DecompileProcess.DisposeState processState) { + super(func, language, compilerSpec, dtm, errorMsg, null, processState); + localDecoder = decoder; + } + + public void processDoc(BasePcodeExporter pfEx) { + try { + this.ex = pfEx; + int documentElem = localDecoder.openElement(ELEM_DOC); + Function f = getFunction(); + String key = f.getName() + "@" + f.getEntryPoint(); + iterateElements(key, documentElem); + localDecoder.closeElement(documentElem); + } + catch (DecoderException e) { // Error while walking the DOM + Msg.error(this, e.getMessage(), e); + return; + } + catch (Exception e) { // Exception with the underlying stream + Msg.error(this, e.getMessage(), e); + return; + } + } + + private void iterateElements(String name, int parentId) throws DecoderException { + PcodeElements parentType = PcodeElements.find(parentId); + int n = 0; + int argn = 0; + int opn = 0; + String highVar = null; + for (;;) { + int childId = localDecoder.peekElement(); + if (childId == 0) { + break; + } + String childName = name + ":" + childId + ":" + n++; + PcodeElements childType = PcodeElements.find(childId); + String fnelem = + "E_" + parentType.name().toUpperCase() + "_" + childType.name().toUpperCase(); + if (parentType.equals(PcodeElements.ELEM_OP) && + (childType.equals(PcodeElements.ELEM_ADDR) || + childType.equals(PcodeElements.ELEM_VOID) || + childType.equals(PcodeElements.ELEM_IOP))) { + if (argn == 0) { + ex.export("E_OP_OUTPUT", name, childName); + } + else { + ex.export("E_OP_INPUT", name, childName); + ex.export("A_INPUT_INDEX", childName, Integer.toString(argn - 1)); + } + argn++; + } + if (parentType.equals(PcodeElements.ELEM_BLOCK) && + childType.equals(PcodeElements.ELEM_OP)) { + ex.export("A_OP_INDEX", childName, Integer.toString(opn)); + opn++; + } + if (parentType.equals(PcodeElements.ELEM_BLOCK) || + parentType.equals(PcodeElements.ELEM_STATEMENT)) { + String astr = childType.name().toUpperCase(); + if (highVar == null && astr.equals("VARIABLE")) { + highVar = childName; + } + else if (highVar != null && astr.equals("FIELD")) { + ex.export("VARIABLE_FIELD", highVar, childName); + } + else if (astr.equals("SYNTAX") || astr.equals("OP")) { + // continue + } + else { + highVar = null; + } + } + localDecoder.openElement(); + ex.export(fnelem, name, childName); + iterateAttributes(childName, childType); + iterateElements(childName, childId); + localDecoder.closeElement(childId); + } + } + + private void iterateAttributes(String childName, PcodeElements childType) + throws DecoderException { + for (;;) { + int attrId = localDecoder.getNextAttributeId(); + if (attrId == 0) { + break; + } + PcodeAttributes attr = PcodeAttributes.find(attrId); + String value = readValue(childType, attr); + String funcAttr = + "A_" + childType.name().toUpperCase() + "_" + attr.name().toUpperCase(); + boolean isAddr = childType.equals(PcodeElements.ELEM_ADDR) || + childType.equals(PcodeElements.ELEM_SEQNUM); + if (isAddr && attr.equals(PcodeAttributes.ATTRIB_SPACE)) { + ex.export(funcAttr, childName, value.substring(0, value.length() - 1)); + continue; + } + ex.export(funcAttr, childName, value); + if (isAddr && (attr.equals(PcodeAttributes.ATTRIB_REF) || + attr.equals(PcodeAttributes.ATTRIB_OFFSET))) { + ex.export("LOCATION_FUNC", childName, + getFunction().getName() + "@" + getFunction().getEntryPoint()); + ex.export("LOCATION_UNIQ", childName, Integer.toString(addressUnique++)); + } + if ((isAddr && attr.equals(PcodeAttributes.ATTRIB_OFFSET)) || + (childType.equals(PcodeElements.ELEM_RANGE) && + (attr.equals(PcodeAttributes.ATTRIB_FIRST) || + attr.equals(PcodeAttributes.ATTRIB_LAST)))) { + // Convenience methods for datalog + try { + if (valueSet.add(value)) { + // Negative numbers need to be converted here + ex.export("LOCATION_NUM", value, + Long.toString(Long.parseUnsignedLong(value))); + ex.export("LOCATION_HEX", value, + Long.toHexString(Long.parseUnsignedLong(value))); + } + } + catch (NumberFormatException nfe) { + Msg.error(this, nfe.getMessage()); + } + } + } + } + + private String readValue(PcodeElements ctype, PcodeAttributes attr) { + try { + if (ctype.equals(PcodeElements.ELEM_IOP) && + attr.equals(PcodeAttributes.ATTRIB_VALUE)) { + return Long.toUnsignedString(localDecoder.readUnsignedInteger()); + } + if (ctype.equals(PcodeElements.ELEM_SPACEID) && + attr.equals(PcodeAttributes.ATTRIB_NAME)) { + return Integer.toUnsignedString(localDecoder.readSpace().getSpaceID()); + } + if (ctype.equals(PcodeElements.ELEM_HIGH) && + attr.equals(PcodeAttributes.ATTRIB_OFFSET)) { + return Long.toString(localDecoder.readSignedInteger()); + } + if (ctype.equals(PcodeElements.ELEM_COMMENT) && + attr.equals(PcodeAttributes.ATTRIB_OFF)) { + return Long.toUnsignedString(localDecoder.readUnsignedInteger()); + } + if (ctype.equals(PcodeElements.ELEM_SYMBOL) && + attr.equals(PcodeAttributes.ATTRIB_INDEX)) { + return Long.toUnsignedString(localDecoder.readUnsignedInteger()); + } + } + catch (DecoderException de) { + // Not a special case...fallback to attr.method. + // If that fails, we report the error. + } + try { + return switch (attr.method()) { + case DecoderMethods.READ_BOOL -> Boolean.toString(localDecoder.readBool()); + case DecoderMethods.READ_SINT -> Long.toString(localDecoder.readSignedInteger()); + case DecoderMethods.READ_UINT -> Long + .toUnsignedString(localDecoder.readUnsignedInteger()); + case DecoderMethods.READ_STRING -> localDecoder.readString(); + case DecoderMethods.READ_SPACE -> localDecoder.readSpace().toString(); + case DecoderMethods.READ_OPCODE -> Integer.toString(localDecoder.readOpcode()); + default -> "UNKNOWN"; + }; + } + catch (DecoderException de) { + Msg.error(this, de.getMessage()); + } + return null; + } +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeAttributes.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeAttributes.java new file mode 100644 index 0000000000..bb4dfbc44c --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeAttributes.java @@ -0,0 +1,424 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * An annotation for a data element being transferred to/from a stream + *

+ * This class parallels the XML concept of an attribute on an element. An PcodeAttributes describes + * a particular piece of data associated with an ElementId. The defining characteristic of the PcodeAttributes is + * its name. Internally this name is associated with an integer id. The name (and id) uniquely determine + * the data being labeled, within the context of a specific ElementId. Within this context, an PcodeAttributes labels either + *

    + *
  • An unsigned integer
  • + *
  • A signed integer
  • + *
  • A boolean value
  • + *
  • A string
  • + *
+ *

+ * The same PcodeAttributes can be used to label a different type of data when associated with a different ElementId. + * + * @param name unique attribute name + * @param id unqiue attribute ID + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.util.HashMap; +import java.util.Map; + +public record PcodeAttributes(String name, int id, DecoderMethods method) { + + // NB: This class parallels AttributeId in FrameworkSoftwareModeling + + private static Map nlookupPcodeAttributes = new HashMap<>(); + private static Map ilookupPcodeAttributes = new HashMap<>(); + + public PcodeAttributes { + // add new attribute to lookup map + if (null != nlookupPcodeAttributes.put(name, this)) { + throw new RuntimeException("Duplicate PcodeAttributes: " + name); + } + if (null != ilookupPcodeAttributes.put(id, this)) { + throw new RuntimeException("Duplicate PcodeAttributes: " + name); + } + } + + /** + * Find the id associated with a specific attribute name + * @param nm the attribute name + * @return the associated id + */ + public static PcodeAttributes find(String nm) { + return nlookupPcodeAttributes.getOrDefault(nm, ATTRIB_UNKNOWN); + } + + public static PcodeAttributes find(int id) { + return ilookupPcodeAttributes.getOrDefault(id, ATTRIB_UNKNOWN); + } + + // Common attributes. Attributes with multiple uses + public static final PcodeAttributes ATTRIB_CONTENT = + new PcodeAttributes("XMLcontent", 1, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_ALIGN = + new PcodeAttributes("align", 2, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_BIGENDIAN = + new PcodeAttributes("bigendian", 3, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_CONSTRUCTOR = + new PcodeAttributes("constructor", 4, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_DESTRUCTOR = + new PcodeAttributes("destructor", 5, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_EXTRAPOP = + new PcodeAttributes("extrapop", 6, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_FORMAT = + new PcodeAttributes("format", 7, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_HIDDENRETPARM = + new PcodeAttributes("hiddenretparm", 8, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_ID = + new PcodeAttributes("id", 9, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_INDEX = + new PcodeAttributes("index", 10, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_INDIRECTSTORAGE = + new PcodeAttributes("indirectstorage", 11, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_METATYPE = + new PcodeAttributes("metatype", 12, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MODEL = + new PcodeAttributes("model", 13, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_NAME = + new PcodeAttributes("name", 14, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_NAMELOCK = + new PcodeAttributes("namelock", 15, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_OFFSET = + new PcodeAttributes("offset", 16, DecoderMethods.READ_UINT); // ?? + public static final PcodeAttributes ATTRIB_READONLY = + new PcodeAttributes("readonly", 17, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_REF = + new PcodeAttributes("ref", 18, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_SIZE = + new PcodeAttributes("size", 19, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_SPACE = + new PcodeAttributes("space", 20, DecoderMethods.READ_SPACE); + public static final PcodeAttributes ATTRIB_THISPTR = + new PcodeAttributes("thisptr", 21, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_TYPE = + new PcodeAttributes("type", 22, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_TYPELOCK = + new PcodeAttributes("typelock", 23, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_VAL = + new PcodeAttributes("val", 24, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_VALUE = + new PcodeAttributes("value", 25, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_WORDSIZE = + new PcodeAttributes("wordsize", 26, DecoderMethods.READ_STRING); + + // address + public static final PcodeAttributes ATTRIB_FIRST = + new PcodeAttributes("first", 27, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_LAST = + new PcodeAttributes("last", 28, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_UNIQ = + new PcodeAttributes("uniq", 29, DecoderMethods.READ_UINT); + + // varnode + public static final PcodeAttributes ATTRIB_ADDRTIED = + new PcodeAttributes("addrtied", 30, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_GRP = + new PcodeAttributes("grp", 31, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_INPUT = + new PcodeAttributes("input", 32, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_PERSISTS = + new PcodeAttributes("persists", 33, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_UNAFF = + new PcodeAttributes("unaff", 34, DecoderMethods.READ_BOOL); + + // prettyprint + public static final PcodeAttributes ATTRIB_BLOCKREF = + new PcodeAttributes("blockref", 35, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_CLOSE = + new PcodeAttributes("close", 36, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_COLOR = + new PcodeAttributes("color", 37, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_INDENT = + new PcodeAttributes("indent", 38, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_OFF = + new PcodeAttributes("off", 39, DecoderMethods.READ_SINT); // READ_UINT? + public static final PcodeAttributes ATTRIB_OPEN = + new PcodeAttributes("open", 40, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_OPREF = + new PcodeAttributes("opref", 41, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_VARREF = + new PcodeAttributes("varref", 42, DecoderMethods.READ_UINT); + + // translate + public static final PcodeAttributes ATTRIB_CODE = + new PcodeAttributes("code", 43, DecoderMethods.READ_OPCODE); + public static final PcodeAttributes ATTRIB_CONTAIN = + new PcodeAttributes("contain", 44, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_DEFAULTSPACE = + new PcodeAttributes("defaultspace", 45, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_UNIQBASE = + new PcodeAttributes("uniqbase", 46, DecoderMethods.READ_STRING); + + // type + public static final PcodeAttributes ATTRIB_ALIGNMENT = + new PcodeAttributes("alignment", 47, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_ARRAYSIZE = + new PcodeAttributes("arraysize", 48, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_CHAR = + new PcodeAttributes("char", 49, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_CORE = + new PcodeAttributes("core", 50, DecoderMethods.READ_BOOL); +// public static final PcodeAttributes ATTRIB_ENUM = +// new PcodeAttributes("enum", 51, DecoderMethods.READ_STRING); // deprecated + public static final PcodeAttributes ATTRIB_INCOMPLETE = + new PcodeAttributes("incomplete", 52, DecoderMethods.READ_STRING); +// public static final PcodeAttributes ATTRIB_ENUMSIZE = +// new PcodeAttributes("enumsize", 53, DecoderMethods.READ_STRING); // deprecated +// public static final PcodeAttributes ATTRIB_INTSIZE = +// new PcodeAttributes("intsize", 54, DecoderMethods.READ_STRING); // deprecated +// public static final PcodeAttributes ATTRIB_LONGSIZE = +// new PcodeAttributes("longsize", 55, DecoderMethods.READ_STRING); // deprecated + public static final PcodeAttributes ATTRIB_OPAQUESTRING = + new PcodeAttributes("opaquestring", 56, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_SIGNED = + new PcodeAttributes("signed", 57, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STRUCTALIGN = + new PcodeAttributes("structalign", 58, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_UTF = + new PcodeAttributes("utf", 59, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_VARLENGTH = + new PcodeAttributes("varlength", 60, DecoderMethods.READ_STRING); + + // database + public static final PcodeAttributes ATTRIB_CAT = + new PcodeAttributes("cat", 61, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_FIELD = + new PcodeAttributes("field", 62, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MERGE = + new PcodeAttributes("merge", 63, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_SCOPEIDBYNAME = + new PcodeAttributes("scopeidbyname", 64, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_VOLATILE = + new PcodeAttributes("volatile", 65, DecoderMethods.READ_BOOL); + + // variable + public static final PcodeAttributes ATTRIB_CLASS = + new PcodeAttributes("class", 66, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_REPREF = + new PcodeAttributes("repref", 67, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_SYMREF = + new PcodeAttributes("symref", 68, DecoderMethods.READ_UINT); + + // stringmanage + public static final PcodeAttributes ATTRIB_TRUNC = + new PcodeAttributes("trunc", 69, DecoderMethods.READ_STRING); + + // pcodeinject + public static final PcodeAttributes ATTRIB_DYNAMIC = + new PcodeAttributes("dynamic", 70, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_INCIDENTALCOPY = + new PcodeAttributes("incidentalcopy", 71, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_INJECT = + new PcodeAttributes("inject", 72, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_PARAMSHIFT = + new PcodeAttributes("paramshift", 73, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_TARGETOP = + new PcodeAttributes("targetop", 74, DecoderMethods.READ_STRING); + + // block + public static final PcodeAttributes ATTRIB_ALTINDEX = + new PcodeAttributes("altindex", 75, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_DEPTH = + new PcodeAttributes("depth", 76, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_END = + new PcodeAttributes("end", 77, DecoderMethods.READ_SINT); + public static final PcodeAttributes ATTRIB_OPCODE = + new PcodeAttributes("opcode", 78, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_REV = + new PcodeAttributes("rev", 79, DecoderMethods.READ_SINT); + + // cpool + public static final PcodeAttributes ATTRIB_A = + new PcodeAttributes("a", 80, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_B = + new PcodeAttributes("b", 81, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_LENGTH = + new PcodeAttributes("length", 82, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_TAG = + new PcodeAttributes("tag", 83, DecoderMethods.READ_STRING); + + // funcdata + public static final PcodeAttributes ATTRIB_NOCODE = + new PcodeAttributes("nocode", 84, DecoderMethods.READ_STRING); + + // userop + public static final PcodeAttributes ATTRIB_FARPOINTER = + new PcodeAttributes("farpointer", 85, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_INPUTOP = + new PcodeAttributes("inputop", 86, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_OUTPUTOP = + new PcodeAttributes("outputop", 87, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_USEROP = + new PcodeAttributes("userop", 88, DecoderMethods.READ_STRING); + + // space + public static final PcodeAttributes ATTRIB_BASE = + new PcodeAttributes("base", 89, DecoderMethods.READ_STRING); +// public static final PcodeAttributes ATTRIB_DEADCODEDELAY = +// new PcodeAttributes("deadcodedelay", 90, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_DELAY = + new PcodeAttributes("delay", 91, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_LOGICALSIZE = + new PcodeAttributes("logicalsize", 92, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_PHYSICAL = + new PcodeAttributes("physical", 93, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_PIECE = + new PcodeAttributes("piece", 94, DecoderMethods.READ_STRING); + + // architecture + public static final PcodeAttributes ATTRIB_ADJUSTVMA = + new PcodeAttributes("adjustvma", 103, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_ENABLE = + new PcodeAttributes("enable", 104, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_GROUP = + new PcodeAttributes("group", 105, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_GROWTH = + new PcodeAttributes("growth", 106, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_KEY = + new PcodeAttributes("key", 107, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_LOADERSYMBOLS = + new PcodeAttributes("loadersymbols", 108, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_PARENT = + new PcodeAttributes("parent", 109, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_REGISTER = + new PcodeAttributes("register", 110, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_REVERSEJUSTIFY = + new PcodeAttributes("reversejustify", 111, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_SIGNEXT = + new PcodeAttributes("signext", 112, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STYLE = + new PcodeAttributes("style", 113, DecoderMethods.READ_STRING); + + // fspec + public static final PcodeAttributes ATTRIB_CUSTOM = + new PcodeAttributes("custom", 114, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_DOTDOTDOT = + new PcodeAttributes("dotdotdot", 115, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_EXTENSION = + new PcodeAttributes("extension", 116, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_HASTHIS = + new PcodeAttributes("hasthis", 117, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_INLINE = + new PcodeAttributes("inline", 118, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_KILLEDBYCALL = + new PcodeAttributes("killedbycall", 119, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MAXSIZE = + new PcodeAttributes("maxsize", 120, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MINSIZE = + new PcodeAttributes("minsize", 121, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MODELLOCK = + new PcodeAttributes("modellock", 122, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_NORETURN = + new PcodeAttributes("noreturn", 123, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_POINTERMAX = + new PcodeAttributes("pointermax", 124, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_SEPARATEFLOAT = + new PcodeAttributes("separatefloat", 125, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STACKSHIFT = + new PcodeAttributes("stackshift", 126, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STRATEGY = + new PcodeAttributes("strategy", 127, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_THISBEFORERETPOINTER = + new PcodeAttributes("thisbeforeretpointer", 128, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_VOIDLOCK = + new PcodeAttributes("voidlock", 129, DecoderMethods.READ_BOOL); + + // transform + public static final PcodeAttributes ATTRIB_VECTOR_LANE_SIZES = + new PcodeAttributes("vector_lane_sizes", 130, DecoderMethods.READ_STRING); + + // jumptable + public static final PcodeAttributes ATTRIB_LABEL = + new PcodeAttributes("label", 131, DecoderMethods.READ_UINT); + public static final PcodeAttributes ATTRIB_NUM = + new PcodeAttributes("num", 132, DecoderMethods.READ_STRING); + + // varmap + public static final PcodeAttributes ATTRIB_LOCK = + new PcodeAttributes("lock", 133, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_MAIN = + new PcodeAttributes("main", 134, DecoderMethods.READ_SPACE); + + // loadimage_xml +// public static final PcodeAttributes ATTRIB_ARCH = +// new PcodeAttributes("arch", 135); + + // sleigh_arch +// public static final PcodeAttributes ATTRIB_DEPRECATED = +// new PcodeAttributes("deprecated", 136); +// public static final PcodeAttributes ATTRIB_ENDIAN = +// new PcodeAttributes("endian", 137); +// public static final PcodeAttributes ATTRIB_PROCESSOR = +// new PcodeAttributes("processor", 138); +// public static final PcodeAttributes ATTRIB_PROCESSORSPEC = +// new PcodeAttributes("processorspec", 139); +// public static final PcodeAttributes ATTRIB_SLAFILE = +// new PcodeAttributes("slafile", 140); +// public static final PcodeAttributes ATTRIB_SPEC = +// new PcodeAttributes("spec", 141); +// public static final PcodeAttributes ATTRIB_TARGET = +// new PcodeAttributes("target", 142); +// public static final PcodeAttributes ATTRIB_VARIANT = +// new PcodeAttributes("variant", 143); +// public static final PcodeAttributes ATTRIB_VERSION = +// new PcodeAttributes("version", 144); + + // signature + public static final PcodeAttributes ATTRIB_BADDATA = + new PcodeAttributes("baddata", 145, DecoderMethods.READ_BOOL); + public static final PcodeAttributes ATTRIB_HASH = + new PcodeAttributes("hash", 146, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_UNIMPL = + new PcodeAttributes("unimpl", 147, DecoderMethods.READ_BOOL); + +// public static final PcodeAttributes ATTRIB_ADDRESS = +// new PcodeAttributes("address", 148, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STORAGE = + new PcodeAttributes("storage", 149, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_STACKSPILL = + new PcodeAttributes("stackspill", 150, DecoderMethods.READ_STRING); + + // modelrules + + public static final PcodeAttributes ATTRIB_SIZES = + new PcodeAttributes("sizes", 151, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_BACKFILL = + new PcodeAttributes("backfill", 152, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MAX_PRIMITIVES = + new PcodeAttributes("maxprimitives", 153, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_REVERSESIGNIF = + new PcodeAttributes("reversesignif", 154, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_MATCHSIZE = + new PcodeAttributes("matchsize", 155, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_AFTER_BYTES = + new PcodeAttributes("afterbytes", 156, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_AFTER_STORAGE = + new PcodeAttributes("afterstorage", 157, DecoderMethods.READ_STRING); + public static final PcodeAttributes ATTRIB_FILL_ALTERNATE = + new PcodeAttributes("fillalternate", 158, DecoderMethods.READ_STRING); + + public static final PcodeAttributes ATTRIB_UNKNOWN = + new PcodeAttributes("XMLunknown", 159, DecoderMethods.READ_STRING); + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeDatabase.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeDatabase.java new file mode 100644 index 0000000000..c2ac67a425 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeDatabase.java @@ -0,0 +1,121 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.io.*; +import java.util.*; +import java.util.concurrent.*; + +import ghidra.util.Msg; + +public class PcodeDatabase { + private static final char DBSEP = '\t'; + private static final char EOL = '\n'; + + protected Map>> contents = new ConcurrentHashMap<>(); + + public void writeFile(Collection> contentList, String predicateFile, + String directory) throws IOException { + File factsFile = new File(directory, predicateFile + ".facts"); + Writer w = new BufferedWriter(new FileWriter(factsFile, true)); + for (List record : contentList) { + writeRecord(w, record); + } + w.flush(); + w.close(); + } + + public synchronized void writeFacts(String directory, boolean writeAll) { + final int k = Runtime.getRuntime().availableProcessors() * 2 - 1; + ExecutorService es = Executors.newFixedThreadPool(k); + for (String fn : contents.keySet()) { + es.execute(() -> { + try { + writeFile(contents.get(fn), fn, directory); + } + catch (Exception e) { + // System.out.println(e); + ghidra.util.Msg.info(this, e); + for (StackTraceElement st : e.getStackTrace()) { + ghidra.util.Msg.info(this, st); + } + } + }); + } + + es.shutdown(); + try { + while (!es.awaitTermination(30, TimeUnit.SECONDS)) + ; + } + catch (Exception e) { + // System.out.println(e); + Msg.info(this, e); + for (StackTraceElement st : e.getStackTrace()) { + ghidra.util.Msg.info(this, st); + } + } + + this.clear(writeAll); + } + + private void writeRecord(Writer writer, List record) throws IOException { + boolean first = true; + for (String col : record) { + if (col == null) { + col = "UNKNOWN"; + } + if (!first) { + writer.write(DBSEP); + } + writeColumn(writer, col); + first = false; + } + writer.write(EOL); + } + + private void writeColumn(Writer writer, String column) throws IOException { + // Quote some special characters. + for (int i = 0; i < column.length(); i++) { + char c = column.charAt(i); + switch (c) { + case '\"' -> writer.write("'"); + case '\\' -> { + writer.write('\\'); + writer.write('\\'); + } + case EOL -> { + writer.write('\\'); + writer.write('n'); + } + case '\t' -> { + writer.write('\\'); + writer.write('t'); + } + default -> writer.write(c); + } + } + } + + public synchronized void addExport(String filename, String... args) { + this.contents.computeIfAbsent(filename, _ -> new HashSet<>()) + .add(Arrays.asList(args)); + } + + public void clear(boolean clearAll) { + contents = new ConcurrentHashMap<>(); + } +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeElements.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeElements.java new file mode 100644 index 0000000000..270eb7ddab --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeElements.java @@ -0,0 +1,511 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * An annotation for a specific collection of hierarchical data + *

+ * This record parallels the XML concept of an element. An ElementId describes a collection of data, where each + * piece is annotated by a specific AttributeId. In addition, each ElementId can contain zero or more child + * ElementId objects, forming a hierarchy of annotated data. Each ElementId has a name, which is unique at least + * within the context of its parent ElementId. Internally this name is associated with an integer id. A special + * AttributeId ATTRIB_CONTENT is used to label the XML element's text content, which is traditionally not labeled + * as an attribute. + * + * @param name unique element name + * @param id unique element ID + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.util.HashMap; +import java.util.Map; + +public record PcodeElements(String name, int id) { + + // NB: This class parallels ElementId in FrameworkSoftwareModeling + + private static Map nlookupElementId = new HashMap<>(); + private static Map ilookupElementId = new HashMap<>(); + + public PcodeElements { + // add new element to lookup map + if (null != nlookupElementId.put(name, this)) { + throw new RuntimeException("Duplicate ElementId instance: " + name); + } + if (null != ilookupElementId.put(id, this)) { + throw new RuntimeException("Duplicate ElementId instance: " + name); + } + } + + /** + * Find the id associated with a specific element name + * @param nm the element name + * @return the associated id + */ + public static PcodeElements find(String nm) { + return nlookupElementId.getOrDefault(nm, ELEM_UNKNOWN); + } + + public static PcodeElements find(Integer id) { + return ilookupElementId.getOrDefault(id, ELEM_UNKNOWN); + } + + public static final PcodeElements ELEM_DATA = new PcodeElements("data", 1); + public static final PcodeElements ELEM_INPUT = new PcodeElements("input", 2); + public static final PcodeElements ELEM_OFF = new PcodeElements("off", 3); + public static final PcodeElements ELEM_OUTPUT = new PcodeElements("output", 4); + public static final PcodeElements ELEM_RETURNADDRESS = new PcodeElements("returnaddress", 5); + public static final PcodeElements ELEM_SYMBOL = new PcodeElements("symbol", 6); + public static final PcodeElements ELEM_TARGET = new PcodeElements("target", 7); + public static final PcodeElements ELEM_VAL = new PcodeElements("val", 8); + public static final PcodeElements ELEM_VALUE = new PcodeElements("value", 9); + public static final PcodeElements ELEM_VOID = new PcodeElements("void", 10); + public static final PcodeElements ELEM_ADDR = new PcodeElements("addr", 11); + + // address + public static final PcodeElements ELEM_RANGE = new PcodeElements("range", 12); + public static final PcodeElements ELEM_RANGELIST = new PcodeElements("rangelist", 13); + public static final PcodeElements ELEM_REGISTER = new PcodeElements("register", 14); + public static final PcodeElements ELEM_SEQNUM = new PcodeElements("seqnum", 15); + public static final PcodeElements ELEM_VARNODE = new PcodeElements("varnode", 16); + + // prettyprint + public static final PcodeElements ELEM_BREAK = new PcodeElements("break", 17); + public static final PcodeElements ELEM_CLANG_DOCUMENT = new PcodeElements("clang_document", 18); + public static final PcodeElements ELEM_FUNCNAME = new PcodeElements("funcname", 19); + public static final PcodeElements ELEM_FUNCPROTO = new PcodeElements("funcproto", 20); + public static final PcodeElements ELEM_LABEL = new PcodeElements("label", 21); + public static final PcodeElements ELEM_RETURN_TYPE = new PcodeElements("return_type", 22); + public static final PcodeElements ELEM_STATEMENT = new PcodeElements("statement", 23); + public static final PcodeElements ELEM_SYNTAX = new PcodeElements("syntax", 24); + public static final PcodeElements ELEM_VARDECL = new PcodeElements("vardecl", 25); + public static final PcodeElements ELEM_VARIABLE = new PcodeElements("variable", 26); + + // transform + public static final PcodeElements ELEM_OP = new PcodeElements("op", 27); + public static final PcodeElements ELEM_SLEIGH = new PcodeElements("sleigh", 28); + public static final PcodeElements ELEM_SPACE = new PcodeElements("space", 29); + public static final PcodeElements ELEM_SPACEID = new PcodeElements("spaceid", 30); + public static final PcodeElements ELEM_SPACES = new PcodeElements("spaces", 31); + public static final PcodeElements ELEM_SPACE_BASE = new PcodeElements("space_base", 32); + public static final PcodeElements ELEM_SPACE_OTHER = new PcodeElements("space_other", 33); + public static final PcodeElements ELEM_SPACE_OVERLAY = new PcodeElements("space_overlay", 34); + public static final PcodeElements ELEM_SPACE_UNIQUE = new PcodeElements("space_unique", 35); + public static final PcodeElements ELEM_TRUNCATE_SPACE = new PcodeElements("truncate_space", 36); + + // type + public static final PcodeElements ELEM_ABSOLUTE_MAX_ALIGNMENT = + new PcodeElements("absolute_max_alignment", 37); + public static final PcodeElements ELEM_BITFIELD_PACKING = + new PcodeElements("bitfield_packing", 38); + public static final PcodeElements ELEM_CHAR_SIZE = new PcodeElements("char_size", 39); + public static final PcodeElements ELEM_CHAR_TYPE = new PcodeElements("char_type", 40); + public static final PcodeElements ELEM_CORETYPES = new PcodeElements("coretypes", 41); + public static final PcodeElements ELEM_DATA_ORGANIZATION = + new PcodeElements("data_organization", 42); + public static final PcodeElements ELEM_DEF = new PcodeElements("def", 43); + public static final PcodeElements ELEM_DEFAULT_ALIGNMENT = + new PcodeElements("default_alignment", 44); + public static final PcodeElements ELEM_DEFAULT_POINTER_ALIGNMENT = + new PcodeElements("default_pointer_alignment", 45); + public static final PcodeElements ELEM_DOUBLE_SIZE = new PcodeElements("double_size", 46); + public static final PcodeElements ELEM_ENTRY = new PcodeElements("entry", 47); + public static final PcodeElements ELEM_ENUM = new PcodeElements("enum", 48); + public static final PcodeElements ELEM_FIELD = new PcodeElements("field", 49); + public static final PcodeElements ELEM_FLOAT_SIZE = new PcodeElements("float_size", 50); + public static final PcodeElements ELEM_INTEGER_SIZE = new PcodeElements("integer_size", 51); + public static final PcodeElements ELEM_LONG_DOUBLE_SIZE = + new PcodeElements("long_double_size", 52); + public static final PcodeElements ELEM_LONG_LONG_SIZE = new PcodeElements("long_long_size", 53); + public static final PcodeElements ELEM_LONG_SIZE = new PcodeElements("long_size", 54); + public static final PcodeElements ELEM_MACHINE_ALIGNMENT = + new PcodeElements("machine_alignment", 55); + public static final PcodeElements ELEM_POINTER_SHIFT = new PcodeElements("pointer_shift", 56); + public static final PcodeElements ELEM_POINTER_SIZE = new PcodeElements("pointer_size", 57); + public static final PcodeElements ELEM_SHORT_SIZE = new PcodeElements("short_size", 58); + public static final PcodeElements ELEM_SIZE_ALIGNMENT_MAP = + new PcodeElements("size_alignment_map", 59); + public static final PcodeElements ELEM_TYPE = new PcodeElements("type", 60); + public static final PcodeElements ELEM_TYPE_ALIGNMENT_ENABLED = + new PcodeElements("type_alignment_enabled", 61); + public static final PcodeElements ELEM_TYPEGRP = new PcodeElements("typegrp", 62); + public static final PcodeElements ELEM_TYPEREF = new PcodeElements("typeref", 63); + public static final PcodeElements ELEM_USE_MS_CONVENTION = + new PcodeElements("use_MS_convention", 64); + public static final PcodeElements ELEM_WCHAR_SIZE = new PcodeElements("wchar_size", 65); + public static final PcodeElements ELEM_ZERO_LENGTH_BOUNDARY = + new PcodeElements("zero_length_boundary", 66); + public static final PcodeElements ELEM_BITFIELD = new PcodeElements("bitfield", 289); + + // database + public static final PcodeElements ELEM_COLLISION = new PcodeElements("collision", 67); + public static final PcodeElements ELEM_DB = new PcodeElements("db", 68); + public static final PcodeElements ELEM_EQUATESYMBOL = new PcodeElements("equatesymbol", 69); + public static final PcodeElements ELEM_EXTERNREFSYMBOL = + new PcodeElements("externrefsymbol", 70); + public static final PcodeElements ELEM_FACETSYMBOL = new PcodeElements("facetsymbol", 71); + public static final PcodeElements ELEM_FUNCTIONSHELL = new PcodeElements("functionshell", 72); + public static final PcodeElements ELEM_HASH = new PcodeElements("hash", 73); + public static final PcodeElements ELEM_HOLE = new PcodeElements("hole", 74); + public static final PcodeElements ELEM_LABELSYM = new PcodeElements("labelsym", 75); + public static final PcodeElements ELEM_MAPSYM = new PcodeElements("mapsym", 76); + public static final PcodeElements ELEM_PARENT = new PcodeElements("parent", 77); + public static final PcodeElements ELEM_PROPERTY_CHANGEPOINT = + new PcodeElements("property_changepoint", 78); + public static final PcodeElements ELEM_RANGEEQUALSSYMBOLS = + new PcodeElements("rangeequalssymbols", 79); + public static final PcodeElements ELEM_SCOPE = new PcodeElements("scope", 80); + public static final PcodeElements ELEM_SYMBOLLIST = new PcodeElements("symbollist", 81); + + // variable + public static final PcodeElements ELEM_HIGH = new PcodeElements("high", 82); + + // stringmanage + public static final PcodeElements ELEM_BYTES = new PcodeElements("bytes", 83); + public static final PcodeElements ELEM_STRING = new PcodeElements("string", 84); + public static final PcodeElements ELEM_STRINGMANAGE = new PcodeElements("stringmanage", 85); + + // comment + public static final PcodeElements ELEM_COMMENT = new PcodeElements("comment", 86); + public static final PcodeElements ELEM_COMMENTDB = new PcodeElements("commentdb", 87); + public static final PcodeElements ELEM_TEXT = new PcodeElements("text", 88); + + // pcodeinject + public static final PcodeElements ELEM_ADDR_PCODE = new PcodeElements("addr_pcode", 89); + public static final PcodeElements ELEM_BODY = new PcodeElements("body", 90); + public static final PcodeElements ELEM_CALLFIXUP = new PcodeElements("callfixup", 91); + public static final PcodeElements ELEM_CALLOTHERFIXUP = new PcodeElements("callotherfixup", 92); + public static final PcodeElements ELEM_CASE_PCODE = new PcodeElements("case_pcode", 93); + public static final PcodeElements ELEM_CONTEXT = new PcodeElements("context", 94); + public static final PcodeElements ELEM_DEFAULT_PCODE = new PcodeElements("default_pcode", 95); + public static final PcodeElements ELEM_INJECT = new PcodeElements("inject", 96); + public static final PcodeElements ELEM_INJECTDEBUG = new PcodeElements("injectdebug", 97); + public static final PcodeElements ELEM_INST = new PcodeElements("inst", 98); + public static final PcodeElements ELEM_PAYLOAD = new PcodeElements("payload", 99); + public static final PcodeElements ELEM_PCODE = new PcodeElements("pcode", 100); + public static final PcodeElements ELEM_SIZE_PCODE = new PcodeElements("size_pcode", 101); + + // block + public static final PcodeElements ELEM_BHEAD = new PcodeElements("bhead", 102); + public static final PcodeElements ELEM_BLOCK = new PcodeElements("block", 103); + public static final PcodeElements ELEM_BLOCKEDGE = new PcodeElements("blockedge", 104); + public static final PcodeElements ELEM_EDGE = new PcodeElements("edge", 105); + + // paramid + public static final PcodeElements ELEM_PARAMMEASURES = new PcodeElements("parammeasures", 106); + public static final PcodeElements ELEM_PROTO = new PcodeElements("proto", 107); + public static final PcodeElements ELEM_RANK = new PcodeElements("rank", 108); + + // cpool + public static final PcodeElements ELEM_CONSTANTPOOL = new PcodeElements("constantpool", 109); + public static final PcodeElements ELEM_CPOOLREC = new PcodeElements("cpoolrec", 110); + public static final PcodeElements ELEM_REF = new PcodeElements("ref", 111); + public static final PcodeElements ELEM_TOKEN = new PcodeElements("token", 112); + + // op + public static final PcodeElements ELEM_IOP = new PcodeElements("iop", 113); + public static final PcodeElements ELEM_UNIMPL = new PcodeElements("unimpl", 114); + + // funcdata + public static final PcodeElements ELEM_AST = new PcodeElements("ast", 115); + public static final PcodeElements ELEM_FUNCTION = new PcodeElements("function", 116); + public static final PcodeElements ELEM_HIGHLIST = new PcodeElements("highlist", 117); + public static final PcodeElements ELEM_JUMPTABLELIST = new PcodeElements("jumptablelist", 118); + public static final PcodeElements ELEM_VARNODES = new PcodeElements("varnodes", 119); + + // globalcontext + public static final PcodeElements ELEM_CONTEXT_DATA = new PcodeElements("context_data", 120); + public static final PcodeElements ELEM_CONTEXT_POINTS = + new PcodeElements("context_points", 121); + public static final PcodeElements ELEM_CONTEXT_POINTSET = + new PcodeElements("context_pointset", 122); + public static final PcodeElements ELEM_CONTEXT_SET = new PcodeElements("context_set", 123); + public static final PcodeElements ELEM_SET = new PcodeElements("set", 124); + public static final PcodeElements ELEM_TRACKED_POINTSET = + new PcodeElements("tracked_pointset", 125); + public static final PcodeElements ELEM_TRACKED_SET = new PcodeElements("tracked_set", 126); + + // userop + public static final PcodeElements ELEM_CONSTRESOLVE = new PcodeElements("constresolve", 127); + public static final PcodeElements ELEM_JUMPASSIST = new PcodeElements("jumpassist", 128); + public static final PcodeElements ELEM_SEGMENTOP = new PcodeElements("segmentop", 129); + + // architecture + public static final PcodeElements ELEM_ADDRESS_SHIFT_AMOUNT = + new PcodeElements("address_shift_amount", 130); + public static final PcodeElements ELEM_AGGRESSIVETRIM = + new PcodeElements("aggressivetrim", 131); + public static final PcodeElements ELEM_COMPILER_SPEC = new PcodeElements("compiler_spec", 132); + public static final PcodeElements ELEM_DATA_SPACE = new PcodeElements("data_space", 133); + public static final PcodeElements ELEM_DEFAULT_MEMORY_BLOCKS = + new PcodeElements("default_memory_blocks", 134); + public static final PcodeElements ELEM_DEFAULT_PROTO = new PcodeElements("default_proto", 135); + public static final PcodeElements ELEM_DEFAULT_SYMBOLS = + new PcodeElements("default_symbols", 136); + public static final PcodeElements ELEM_EVAL_CALLED_PROTOTYPE = + new PcodeElements("eval_called_prototype", 137); + public static final PcodeElements ELEM_EVAL_CURRENT_PROTOTYPE = + new PcodeElements("eval_current_prototype", 138); + public static final PcodeElements ELEM_EXPERIMENTAL_RULES = + new PcodeElements("experimental_rules", 139); + public static final PcodeElements ELEM_FLOWOVERRIDELIST = + new PcodeElements("flowoverridelist", 140); + public static final PcodeElements ELEM_FUNCPTR = new PcodeElements("funcptr", 141); + public static final PcodeElements ELEM_GLOBAL = new PcodeElements("global", 142); + public static final PcodeElements ELEM_INCIDENTALCOPY = + new PcodeElements("incidentalcopy", 143); + public static final PcodeElements ELEM_INFERPTRBOUNDS = + new PcodeElements("inferptrbounds", 144); + public static final PcodeElements ELEM_MODELALIAS = new PcodeElements("modelalias", 145); + public static final PcodeElements ELEM_NOHIGHPTR = new PcodeElements("nohighptr", 146); + public static final PcodeElements ELEM_PROCESSOR_SPEC = + new PcodeElements("processor_spec", 147); + public static final PcodeElements ELEM_PROGRAMCOUNTER = + new PcodeElements("programcounter", 148); + public static final PcodeElements ELEM_PROPERTIES = new PcodeElements("properties", 149); + public static final PcodeElements ELEM_PROPERTY = new PcodeElements("property", 150); + public static final PcodeElements ELEM_READONLY = new PcodeElements("readonly", 151); + public static final PcodeElements ELEM_REGISTER_DATA = new PcodeElements("register_data", 152); + public static final PcodeElements ELEM_RULE = new PcodeElements("rule", 153); + public static final PcodeElements ELEM_SAVE_STATE = new PcodeElements("save_state", 154); + public static final PcodeElements ELEM_SEGMENTED_ADDRESS = + new PcodeElements("segmented_address", 155); + public static final PcodeElements ELEM_SPACEBASE = new PcodeElements("spacebase", 156); + public static final PcodeElements ELEM_SPECEXTENSIONS = + new PcodeElements("specextensions", 157); + public static final PcodeElements ELEM_STACKPOINTER = new PcodeElements("stackpointer", 158); + public static final PcodeElements ELEM_VOLATILE = new PcodeElements("volatile", 159); + + // fspec + public static final PcodeElements ELEM_GROUP = new PcodeElements("group", 160); + public static final PcodeElements ELEM_INTERNALLIST = new PcodeElements("internallist", 161); + public static final PcodeElements ELEM_KILLEDBYCALL = new PcodeElements("killedbycall", 162); + public static final PcodeElements ELEM_LIKELYTRASH = new PcodeElements("likelytrash", 163); + public static final PcodeElements ELEM_LOCALRANGE = new PcodeElements("localrange", 164); + public static final PcodeElements ELEM_MODEL = new PcodeElements("model", 165); + public static final PcodeElements ELEM_PARAM = new PcodeElements("param", 166); + public static final PcodeElements ELEM_PARAMRANGE = new PcodeElements("paramrange", 167); + public static final PcodeElements ELEM_PENTRY = new PcodeElements("pentry", 168); + public static final PcodeElements ELEM_PROTOTYPE = new PcodeElements("prototype", 169); + public static final PcodeElements ELEM_RESOLVEPROTOTYPE = + new PcodeElements("resolveprototype", 170); + public static final PcodeElements ELEM_RETPARAM = new PcodeElements("retparam", 171); + public static final PcodeElements ELEM_RETURNSYM = new PcodeElements("returnsym", 172); + public static final PcodeElements ELEM_UNAFFECTED = new PcodeElements("unaffected", 173); + public static final PcodeElements ELEM_INTERNAL_STORAGE = + new PcodeElements("internal_storage", 286); + + // options + public static final PcodeElements ELEM_ALIASBLOCK = new PcodeElements("aliasblock", 174); + public static final PcodeElements ELEM_ALLOWCONTEXTSET = + new PcodeElements("allowcontextset", 175); + public static final PcodeElements ELEM_ANALYZEFORLOOPS = + new PcodeElements("analyzeforloops", 176); + public static final PcodeElements ELEM_COMMENTHEADER = new PcodeElements("commentheader", 177); + public static final PcodeElements ELEM_COMMENTINDENT = new PcodeElements("commentindent", 178); + public static final PcodeElements ELEM_COMMENTINSTRUCTION = + new PcodeElements("commentinstruction", 179); + public static final PcodeElements ELEM_COMMENTSTYLE = new PcodeElements("commentstyle", 180); + public static final PcodeElements ELEM_CONVENTIONPRINTING = + new PcodeElements("conventionprinting", 181); + public static final PcodeElements ELEM_CURRENTACTION = new PcodeElements("currentaction", 182); + public static final PcodeElements ELEM_DEFAULTPROTOTYPE = + new PcodeElements("defaultprototype", 183); + public static final PcodeElements ELEM_ERRORREINTERPRETED = + new PcodeElements("errorreinterpreted", 184); + public static final PcodeElements ELEM_ERRORTOOMANYINSTRUCTIONS = + new PcodeElements("errortoomanyinstructions", 185); + public static final PcodeElements ELEM_ERRORUNIMPLEMENTED = + new PcodeElements("errorunimplemented", 186); + public static final PcodeElements ELEM_BADDATACOUNT = new PcodeElements("baddatacount", 290); + public static final PcodeElements ELEM_EXTRAPOP = new PcodeElements("extrapop", 187); + public static final PcodeElements ELEM_IGNOREUNIMPLEMENTED = + new PcodeElements("ignoreunimplemented", 188); + public static final PcodeElements ELEM_INDENTINCREMENT = + new PcodeElements("indentincrement", 189); + public static final PcodeElements ELEM_INFERCONSTPTR = new PcodeElements("inferconstptr", 190); + public static final PcodeElements ELEM_INLINE = new PcodeElements("inline", 191); + public static final PcodeElements ELEM_INPLACEOPS = new PcodeElements("inplaceops", 192); + public static final PcodeElements ELEM_INTEGERFORMAT = new PcodeElements("integerformat", 193); + public static final PcodeElements ELEM_JUMPLOAD = new PcodeElements("jumpload", 194); + public static final PcodeElements ELEM_MAXINSTRUCTION = + new PcodeElements("maxinstruction", 195); + public static final PcodeElements ELEM_MAXLINEWIDTH = new PcodeElements("maxlinewidth", 196); + public static final PcodeElements ELEM_NAMESPACESTRATEGY = + new PcodeElements("namespacestrategy", 197); + public static final PcodeElements ELEM_NOCASTPRINTING = + new PcodeElements("nocastprinting", 198); + public static final PcodeElements ELEM_NORETURN = new PcodeElements("noreturn", 199); + public static final PcodeElements ELEM_NULLPRINTING = new PcodeElements("nullprinting", 200); + public static final PcodeElements ELEM_OPTIONSLIST = new PcodeElements("optionslist", 201); + public static final PcodeElements ELEM_PARAM1 = new PcodeElements("param1", 202); + public static final PcodeElements ELEM_PARAM2 = new PcodeElements("param2", 203); + public static final PcodeElements ELEM_PARAM3 = new PcodeElements("param3", 204); + public static final PcodeElements ELEM_PROTOEVAL = new PcodeElements("protoeval", 205); + public static final PcodeElements ELEM_SETACTION = new PcodeElements("setaction", 206); + public static final PcodeElements ELEM_SETLANGUAGE = new PcodeElements("setlanguage", 207); + public static final PcodeElements ELEM_STRUCTALIGN = new PcodeElements("structalign", 208); + public static final PcodeElements ELEM_TOGGLERULE = new PcodeElements("togglerule", 209); + public static final PcodeElements ELEM_WARNING = new PcodeElements("warning", 210); + + public static final PcodeElements ELEM_BRACEFORMAT = new PcodeElements("braceformat", 284); + + // jumptable + public static final PcodeElements ELEM_BASICOVERRIDE = new PcodeElements("basicoverride", 211); + public static final PcodeElements ELEM_DEST = new PcodeElements("dest", 212); + public static final PcodeElements ELEM_JUMPTABLE = new PcodeElements("jumptable", 213); + public static final PcodeElements ELEM_LOADTABLE = new PcodeElements("loadtable", 214); + public static final PcodeElements ELEM_NORMADDR = new PcodeElements("normaddr", 215); + public static final PcodeElements ELEM_NORMHASH = new PcodeElements("normhash", 216); + public static final PcodeElements ELEM_STARTVAL = new PcodeElements("startval", 217); + + // override + public static final PcodeElements ELEM_DEADCODEDELAY = new PcodeElements("deadcodedelay", 218); + public static final PcodeElements ELEM_FLOW = new PcodeElements("flow", 219); +// public static final ElementId ELEM_FORCEGOTO = new ElementId("forcegoto", 220); + public static final PcodeElements ELEM_CALLDEST = new PcodeElements("calldest", 221); +// public static final ElementId ELEM_MULTISTAGEJUMP = new ElementId("multistagejump", 222); + public static final PcodeElements ELEM_OVERRIDE = new PcodeElements("override", 223); + public static final PcodeElements ELEM_PROTOOVERRIDE = new PcodeElements("protooverride", 224); + + // prefersplit + public static final PcodeElements ELEM_PREFERSPLIT = new PcodeElements("prefersplit", 225); + + // callgraph + public static final PcodeElements ELEM_CALLGRAPH = new PcodeElements("callgraph", 226); + public static final PcodeElements ELEM_NODE = new PcodeElements("node", 227); + + // varmap + public static final PcodeElements ELEM_LOCALDB = new PcodeElements("localdb", 228); + + // ghidra_process + public static final PcodeElements ELEM_DOC = new PcodeElements("doc", 229); + + // loadimage_xml +// public static final ElementId ELEM_BINARYIMAGE = new ElementId("binaryimage", 230); +// public static final ElementId ELEM_BYTECHUNK = new ElementId("bytechunk", 231); + + // sleigh_arch +// public static final ElementId ELEM_COMPILER = new ElementId("compiler", 232); +// public static final ElementId ELEM_DESCRIPTION = new ElementId("description", 233); +// public static final ElementId ELEM_LANGUAGE = new ElementId("language", 234); +// public static final ElementId ELEM_LANGUAGE_DEFINITIONS = +// new ElementId("language_definitions", 235); + + // xml_arch +// public static final ElementId ELEM_XML_SAVEFILE = new ElementId("xml_savefile", 236); + + // raw_arch +// public static final ElementId ELEM_RAW_SAVEFILE = new ElementId("raw_savefile", 237); + + // ghidra_arch + public static final int COMMAND_ISNAMEUSED = 239; + public static final PcodeElements ELEM_COMMAND_ISNAMEUSED = + new PcodeElements("command_isnameused", COMMAND_ISNAMEUSED); + public static final int COMMAND_GETBYTES = 240; + public static final PcodeElements ELEM_COMMAND_GETBYTES = + new PcodeElements("command_getbytes", COMMAND_GETBYTES); + public static final int COMMAND_GETCALLFIXUP = 241; + public static final PcodeElements ELEM_COMMAND_GETCALLFIXUP = + new PcodeElements("command_getcallfixup", COMMAND_GETCALLFIXUP); + public static final int COMMAND_GETCALLMECH = 242; + public static final PcodeElements ELEM_COMMAND_GETCALLMECH = + new PcodeElements("command_getcallmech", COMMAND_GETCALLMECH); + public static final int COMMAND_GETCALLOTHERFIXUP = 243; + public static final PcodeElements ELEM_COMMAND_GETCALLOTHERFIXUP = + new PcodeElements("command_getcallotherfixup", COMMAND_GETCALLOTHERFIXUP); + public static final int COMMAND_GETCODELABEL = 244; + public static final PcodeElements ELEM_COMMAND_GETCODELABEL = + new PcodeElements("command_getcodelabel", COMMAND_GETCODELABEL); + public static final int COMMAND_GETCOMMENTS = 245; + public static final PcodeElements ELEM_COMMAND_GETCOMMENTS = + new PcodeElements("command_getcomments", COMMAND_GETCOMMENTS); + public static final int COMMAND_GETCPOOLREF = 246; + public static final PcodeElements ELEM_COMMAND_GETCPOOLREF = + new PcodeElements("command_getcpoolref", COMMAND_GETCPOOLREF); + public static final int COMMAND_GETDATATYPE = 247; + public static final PcodeElements ELEM_COMMAND_GETDATATYPE = + new PcodeElements("command_getdatatype", COMMAND_GETDATATYPE); + public static final int COMMAND_GETEXTERNALREF = 248; + public static final PcodeElements ELEM_COMMAND_GETEXTERNALREF = + new PcodeElements("command_getexternalref", COMMAND_GETEXTERNALREF); + public static final int COMMAND_GETMAPPEDSYMBOLS = 249; + public static final PcodeElements ELEM_COMMAND_GETMAPPEDSYMBOLS = + new PcodeElements("command_getmappedsymbols", COMMAND_GETMAPPEDSYMBOLS); + public static final int COMMAND_GETNAMESPACEPATH = 250; + public static final PcodeElements ELEM_COMMAND_GETNAMESPACEPATH = + new PcodeElements("command_getnamespacepath", COMMAND_GETNAMESPACEPATH); + public static final int COMMAND_GETPCODE = 251; + public static final PcodeElements ELEM_COMMAND_GETPCODE = + new PcodeElements("command_getpcode", COMMAND_GETPCODE); + public static final int COMMAND_GETPCODEEXECUTABLE = 252; + public static final PcodeElements ELEM_COMMAND_GETPCODEEXECUTABLE = + new PcodeElements("command_getpcodeexecutable", COMMAND_GETPCODEEXECUTABLE); + public static final int COMMAND_GETREGISTER = 253; + public static final PcodeElements ELEM_COMMAND_GETREGISTER = + new PcodeElements("command_getregister", COMMAND_GETREGISTER); + public static final int COMMAND_GETREGISTERNAME = 254; + public static final PcodeElements ELEM_COMMAND_GETREGISTERNAME = + new PcodeElements("command_getregistername", COMMAND_GETREGISTERNAME); + public static final int COMMAND_GETSTRINGDATA = 255; + public static final PcodeElements ELEM_COMMAND_GETSTRINGDATA = + new PcodeElements("command_getstring", COMMAND_GETSTRINGDATA); + public static final int COMMAND_GETTRACKEDREGISTERS = 256; + public static final PcodeElements ELEM_COMMAND_GETTRACKEDREGISTERS = + new PcodeElements("command_gettrackedregisters", COMMAND_GETTRACKEDREGISTERS); + public static final int COMMAND_GETUSEROPNAME = 257; + public static final PcodeElements ELEM_COMMAND_GETUSEROPNAME = + new PcodeElements("command_getuseropname", COMMAND_GETUSEROPNAME); + + // signature + public static final PcodeElements ELEM_BLOCKSIG = new PcodeElements("blocksig", 258); + public static final PcodeElements ELEM_CALL = new PcodeElements("call", 259); + public static final PcodeElements ELEM_GENSIG = new PcodeElements("gensig", 260); + public static final PcodeElements ELEM_MAJOR = new PcodeElements("major", 261); + public static final PcodeElements ELEM_MINOR = new PcodeElements("minor", 262); + public static final PcodeElements ELEM_COPYSIG = new PcodeElements("copysig", 263); + public static final PcodeElements ELEM_SETTINGS = new PcodeElements("settings", 264); + public static final PcodeElements ELEM_SIG = new PcodeElements("sig", 265); + public static final PcodeElements ELEM_SIGNATUREDESC = new PcodeElements("signaturedesc", 266); + public static final PcodeElements ELEM_SIGNATURES = new PcodeElements("signatures", 267); + public static final PcodeElements ELEM_SIGSETTINGS = new PcodeElements("sigsettings", 268); + public static final PcodeElements ELEM_VARSIG = new PcodeElements("varsig", 269); + + public static final PcodeElements ELEM_SPLITDATATYPE = new PcodeElements("splitdatatype", 270); + public static final PcodeElements ELEM_JUMPTABLEMAX = new PcodeElements("jumptablemax", 271); + public static final PcodeElements ELEM_NANIGNORE = new PcodeElements("nanignore", 272); + + // modelrules + public static final PcodeElements ELEM_DATATYPE = new PcodeElements("datatype", 273); + public static final PcodeElements ELEM_CONSUME = new PcodeElements("consume", 274); + public static final PcodeElements ELEM_CONSUME_EXTRA = new PcodeElements("consume_extra", 275); + public static final PcodeElements ELEM_CONVERT_TO_PTR = + new PcodeElements("convert_to_ptr", 276); + public static final PcodeElements ELEM_GOTO_STACK = new PcodeElements("goto_stack", 277); + public static final PcodeElements ELEM_JOIN = new PcodeElements("join", 278); + public static final PcodeElements ELEM_DATATYPE_AT = new PcodeElements("datatype_at", 279); + public static final PcodeElements ELEM_POSITION = new PcodeElements("position", 280); + public static final PcodeElements ELEM_VARARGS = new PcodeElements("varargs", 281); + public static final PcodeElements ELEM_HIDDEN_RETURN = new PcodeElements("hidden_return", 282); + public static final PcodeElements ELEM_JOIN_PER_PRIMITIVE = + new PcodeElements("join_per_primitive", 283); + public static final PcodeElements ELEM_JOIN_DUAL_CLASS = + new PcodeElements("join_dual_class", 285); + public static final PcodeElements ELEM_EXTRA_STACK = new PcodeElements("extra_stack", 287); + public static final PcodeElements ELEM_CONSUME_REMAINING = + new PcodeElements("consume_remaining", 288); + + public static final PcodeElements ELEM_UNKNOWN = new PcodeElements("XMLunknown", 291); +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeExporter.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeExporter.java new file mode 100644 index 0000000000..4b8155f828 --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/export/PcodeExporter.java @@ -0,0 +1,312 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.decompiler.export; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.*; + +import org.apache.commons.lang3.ArrayUtils; + +import ghidra.pcodeCPort.opcodes.OpCode; +import ghidra.program.model.address.*; +import ghidra.program.model.data.*; +import ghidra.program.model.data.Enum; +import ghidra.program.model.lang.*; +import ghidra.program.model.listing.*; +import ghidra.program.model.mem.MemoryAccessException; +import ghidra.program.model.mem.MemoryBlock; +import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.SymbolIterator; + +public class PcodeExporter extends BasePcodeExporter { + + public String LANGUAGE = "CTADLLanguage"; + public String PROGRAM_FILE = "PROGRAM_FILE"; + + private String REGISTER_OFF_NAME = "REGISTER_OFF_NAME"; + private String REGISTER_IS_SP = "REGISTER_IS_SP"; + private String SPACE_OFFSET = "SPACE_OFFSET"; + private String DATA_STRING = "DATA_STRING"; + private String FUNC_ISEXT = "FUNC_ISEXT"; + private String FUNC_PARAMETER = "FUNC_PARAMETER"; + private String FUNC_PARAMETER_COUNT = "FUNC_PARAMETER_COUNT"; + private String FUNC_PARAMETER_DATATYPE = "FUNC_PARAMETER_DATATYPE"; + private String MNEMONICS = "MNEMONICS"; + private String TABLE = "TABLE"; + + private final Set types = new HashSet(); + private final Set

vtables = new HashSet
(); + + public PcodeExporter(String directory) throws IOException { + super(directory); + } + + public void exportRegisterInfo(Program program) { + Language language = program.getLanguage(); + CompilerSpec cSpec = program.getCompilerSpec(); + Register sp = cSpec.getStackPointer(); + + for (Register reg : language.getRegisters()) { + if (reg.getAddress().isRegisterAddress()) { + db.addExport(REGISTER_OFF_NAME, Long.toString(reg.getAddress().getOffset()), + Integer.toString(reg.getMinimumByteSize()), reg.getName()); + if (sp != null && (sp.equals(reg) || sp.contains(reg))) { + db.addExport(REGISTER_IS_SP, reg.getName()); + } + } + } + } + + public void exportMnemonics(Program program) { + for (OpCode op : OpCode.values()) { + export(MNEMONICS, Integer.toString(op.ordinal()), op.getName()); + } + } + + public void exportAddressSpaces(Program program) { + for (AddressSpace space : program.getAddressFactory().getAddressSpaces()) { + export(SPACE_OFFSET, space.getName(), + Integer.toString(space.getSpaceID())); + } + } + + public void exportDefinedData(Program p) { + DataIterator dataIter = p.getListing().getDefinedData(p.getMinAddress(), true); + for (Data d : dataIter) { + if (!isString(d.getMnemonicString())) + continue; + Address addr = d.getAddress(); + export(DATA_STRING, addressString(addr), d.getValue().toString()); + } + } + + public void externalFunctionParameters(Program currentProgram) { + currentProgram.getFunctionManager().getFunctions(true).forEach(f -> { + db.addExport(FUNC_PARAMETER_COUNT, f.getName(), + Integer.toString(f.getParameterCount())); + for (Parameter p : f.getParameters()) { + db.addExport(FUNC_PARAMETER, f.getName(), Integer.toString(p.getOrdinal()), + p.getName()); + db.addExport(FUNC_PARAMETER_DATATYPE, f.getName(), + Integer.toString(p.getOrdinal()), dtID(p.getDataType())); + } + }); + currentProgram.getFunctionManager().getExternalFunctions().forEach(f -> { + db.addExport(FUNC_ISEXT, f.getName()); + db.addExport(FUNC_PARAMETER_COUNT, f.getName(), + Integer.toString(f.getParameterCount())); + for (Parameter p : f.getParameters()) { + db.addExport(FUNC_PARAMETER, f.getName(), Integer.toString(p.getOrdinal()), + p.getName()); + db.addExport(FUNC_PARAMETER_DATATYPE, f.getName(), + Integer.toString(p.getOrdinal()), dtID(p.getDataType())); + } + }); + } + + private void exportType(DataType dataType) { + String id = dtID(dataType); + if (!types.add(id)) + return; + + export("TYPE_NAME", id, id); + export("TYPE_LENGTH", id, Integer.toString(dataType.getLength())); + while (dataType instanceof TypeDef) { + TypeDef typedef = (TypeDef) dataType; + dataType = typedef.getBaseDataType(); + } + if (dataType instanceof Pointer) { + export("TYPE_TYPE", id, "pointer"); + DataType baseType = ((Pointer) dataType).getDataType(); + if (baseType != null) { + export("TYPE_POINTER_BASE", id, dtID(baseType)); + exportType(baseType); + } + } + if (dataType instanceof Array arr) { + export("TYPE_TYPE", id, "array"); + export("TYPE_ARRAY_BASE", id, dtID(arr.getDataType())); + export("TYPE_ARRAY_N", id, Integer.toString(arr.getNumElements())); + export("TYPE_ARRAY_ELEMENT_LENGTH", id, Integer.toString(arr.getElementLength())); + exportType(arr.getDataType()); + } + if (dataType instanceof Structure struct) { + export("TYPE_TYPE", id, "struct"); + export("TYPE_STRUCT_FIELD_COUNT", id, Integer.toString(struct.getNumComponents())); + for (int i = 0; i < struct.getNumComponents(); i++) { + DataTypeComponent dtc = struct.getComponent(i); + exportComponent("TYPE_STRUCT", id, i, dtc); + } + } + if (dataType instanceof Union union) { + export("TYPE_TYPE", id, "union"); + export("TYPE_UNION_FIELD_COUNT", id, Integer.toString(union.getNumComponents())); + for (int i = 0; i < union.getNumComponents(); i++) { + DataTypeComponent dtc = union.getComponent(i); + exportComponent("TYPE_UNION", id, i, dtc); + } + } + if (dataType instanceof FunctionDefinition fd) { + export("TYPE_TYPE", id, "function"); + export("TYPE_FUNC_RET", id, fd.getReturnType().toString()); + exportType(fd.getReturnType()); + if (fd.hasVarArgs()) { + export("TYPE_FUNC_VARARGS", id, id); + } + ParameterDefinition[] arguments = fd.getArguments(); + export("TYPE_FUNC_PARAM_COUNT", id, Integer.toString(arguments.length)); + for (int i = 0; i < arguments.length; i++) { + export("TYPE_FUNC_PARAM", id, arguments[i] + ":" + i); + exportType(arguments[i].getDataType()); + } + } + if (dataType instanceof BooleanDataType) { + export("TYPE_TYPE", id, "boolean"); + } + if (dataType instanceof AbstractIntegerDataType) { + export("TYPE_TYPE", id, "integer"); + } + if (dataType instanceof AbstractFloatDataType) { + export("TYPE_TYPE", id, "float"); + } + if (dataType instanceof Enum) { + export("TYPE_TYPE", id, "enum"); + } + } + + private void exportComponent(String label, String id, int i, DataTypeComponent dtc) { + String dtcid = dtID(dtc.getDataType()); + export(label + "_FIELD", id, dtcid + ":" + i); + export(label + "_OFFSET", id, dtc.getOffset() + ":" + i); + export(label + "_OFFSET_N", id, dtc.getOffset() + ":" + i); + if (dtc.getFieldName() != null && !dtc.getFieldName().isEmpty()) { + export(label + "_FIELD_NAME", id, dtc.getFieldName() + ":" + i); + //export(label + "_FIELD_NAME_BY_OFFSET", id, dtc.getOffset(), + // dtc.getFieldName() + ":" + i); + } + exportType(dtc.getDataType()); + } + + private String dtID(DataType dt) { + if (dt.getName() != null) { + return dt.getName().replaceAll(" ", ""); + } + return dt.toString(); + } + + public void processVTable(Program program, Symbol sym) { + StringBuilder className = new StringBuilder(); + for (String s : sym.getPath()) { + className.append("::" + s); + } + Address addr = sym.getAddress(); + if (program.getMemory().getBlock(addr).isExternalBlock()) + return; + // SymbolTable symbolTable = program.getSymbolTable(); + AddressFactory addrFactory = program.getAddressFactory(); + int ptrBytes = program.getAddressFactory().getDefaultAddressSpace().getSize() / 8; + + // Skip first two addresses to get to function pointer table + // BigInteger classOffset = readInteger(program, addr, ptrBytes); + addr = addr.add(ptrBytes); + // BigInteger typeInfo = readInteger(program, addr, ptrBytes); + addr = addr.add(ptrBytes); + Address tableAddr = addr; + + // Reads function pointer table + int funOffset = 0; + BigInteger funPtrInt; + Address funPtrAddr; + while (true) { + // Breaks if we hit another vtable + if (vtables.contains(addr)) { + break; + } + + // read next function pointer + funPtrInt = readInteger(program, addr, ptrBytes); + funPtrAddr = addrFactory.getAddress(addrFactory.getDefaultAddressSpace().getSpaceID(), + funPtrInt.longValue()); + + // The table ends when one of three things is true: + // 1. Reading a zero + if (funPtrInt == BigInteger.ZERO) { + break; + } + + // 2. If there are defined symbols, we are out of the vtable, so break + // if (symbolTable.getSymbols(funPtrAddr).length > 0) + // break; + + // emit fact + db.addExport(TABLE, className.toString(), addressString(tableAddr), + Integer.toString(funOffset * ptrBytes), funPtrInt.toString()); + // + // 3. if next block is different from ours, break + MemoryBlock blockPred = program.getMemory().getBlock(funPtrAddr); + MemoryBlock blockSucc = program.getMemory().getBlock(funPtrAddr.add(ptrBytes)); + if (!Objects.equals(blockPred, blockSucc)) { + break; + } + + addr = addr.add(ptrBytes); + funOffset++; + } + } + + public void processVTables(Program program) { + SymbolIterator vtableSymbols = program.getSymbolTable().getSymbols("vtable"); + while (vtableSymbols.hasNext()) { + Symbol sym = vtableSymbols.next(); + processVTable(program, sym); + } + } + + private BigInteger readInteger(Program program, Address addr, int size) { + //AddressFactory addrFactory = program.getAddressFactory(); + //int spaceID = addr.getAddressSpace().getSpaceID(); + try { + byte[] dest = new byte[size]; + program.getMemory().getBytes(addr, dest, 0, size); + if (!program.getLanguage().isBigEndian()) { + ArrayUtils.reverse(dest); + } + return new BigInteger(dest); + } + catch (MemoryAccessException e) { + debug("MemoryAccessException, skipping: " + e); + return BigInteger.ZERO; + } + } + + private String addressString(Address addr) { + return Long.toString(addr.getOffset()); + } + + boolean isString(String mnemonic) { + return switch (mnemonic) { + case "ds" -> true; + case "unicode" -> true; + case "p_unicode" -> true; + case "p_string" -> true; + case "p_string255" -> true; + case "mbcs" -> true; + default -> false; + }; + } + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java index c487a16c3d..7908b3cbdc 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java @@ -20,7 +20,8 @@ import java.util.*; import com.contrastsecurity.sarif.LogicalLocation; import com.contrastsecurity.sarif.Run; -import ghidra.app.decompiler.*; +import ghidra.app.decompiler.ClangFunction; +import ghidra.app.decompiler.ClangToken; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.pcode.*; @@ -116,7 +117,7 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address if (fqname.endsWith(":"+ast.getUniqueId())) { return hvName; } - if (fqname.contains(":"+hvName)) { + if (fqname.contains(":" + hvName)) { return hvName; } if (fqname.contains(":"+ast.getAddress())) { diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintGraphRunHandler.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintGraphRunHandler.java index 3edc4cd401..2e906a8015 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintGraphRunHandler.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintGraphRunHandler.java @@ -38,7 +38,8 @@ public class SarifTaintGraphRunHandler extends SarifGraphRunHandler { service = tool.getService(TaintService.class); } Address addr = controller.locationToAddress(run, n.getLocation()); - vertex.setName(addr.toString()); + String addrStr = addr == null ? "NULL" : addr.toString(true); + vertex.setName(addrStr); String text = n.getLabel().getText(); PropertyBag properties = n.getProperties(); if (properties != null) { @@ -50,7 +51,7 @@ public class SarifTaintGraphRunHandler extends SarifGraphRunHandler { } } vertex.setAttribute("Label", text); - vertex.setAttribute("Address", addr.toString(true)); + vertex.setAttribute("Address", addrStr); LogicalLocation ll = SarifUtils.getLogicalLocation(run, n.getLocation()); if (ll != null) { String name = ll.getName();