diff --git a/python/tools/recorded-call-graph-metrics/ql/BytecodeExpr.qll b/python/tools/recorded-call-graph-metrics/ql/BytecodeExpr.qll index 225d3cc6036..a63416ed65c 100644 --- a/python/tools/recorded-call-graph-metrics/ql/BytecodeExpr.qll +++ b/python/tools/recorded-call-graph-metrics/ql/BytecodeExpr.qll @@ -2,6 +2,12 @@ import python abstract class XMLBytecodeExpr extends XMLElement { } +class XMLBytecodeConst extends XMLBytecodeExpr { + XMLBytecodeConst() { this.hasName("BytecodeConst") } + + string get_value_data_raw() { result = this.getAChild("value").getTextValue() } +} + class XMLBytecodeVariableName extends XMLBytecodeExpr { XMLBytecodeVariableName() { this.hasName("BytecodeVariableName") } @@ -16,6 +22,30 @@ class XMLBytecodeAttribute extends XMLBytecodeExpr { XMLBytecodeExpr get_object_data() { result.getParent() = this.getAChild("object") } } +class XMLBytecodeSubscript extends XMLBytecodeExpr { + XMLBytecodeSubscript() { this.hasName("BytecodeSubscript") } + + XMLBytecodeExpr get_key_data() { result.getParent() = this.getAChild("key") } + + XMLBytecodeExpr get_object_data() { result.getParent() = this.getAChild("object") } +} + +class XMLBytecodeTuple extends XMLBytecodeExpr { + XMLBytecodeTuple() { this.hasName("BytecodeTuple") } + + XMLBytecodeExpr get_elements_data(int index) { + result = this.getAChild("elements").getChild(index) + } +} + +class XMLBytecodeList extends XMLBytecodeExpr { + XMLBytecodeList() { this.hasName("BytecodeList") } + + XMLBytecodeExpr get_elements_data(int index) { + result = this.getAChild("elements").getChild(index) + } +} + class XMLBytecodeCall extends XMLBytecodeExpr { XMLBytecodeCall() { this.hasName("BytecodeCall") } @@ -24,4 +54,20 @@ class XMLBytecodeCall extends XMLBytecodeExpr { class XMLBytecodeUnknown extends XMLBytecodeExpr { XMLBytecodeUnknown() { this.hasName("BytecodeUnknown") } + + string get_opname_data() { result = this.getAChild("opname").getTextValue() } +} + +class XMLBytecodeMakeFunction extends XMLBytecodeExpr { + XMLBytecodeMakeFunction() { this.hasName("BytecodeMakeFunction") } + + XMLBytecodeExpr get_qualified_name_data() { + result.getParent() = this.getAChild("qualified_name") + } +} + +class XMLSomethingInvolvingScaryBytecodeJump extends XMLBytecodeExpr { + XMLSomethingInvolvingScaryBytecodeJump() { this.hasName("SomethingInvolvingScaryBytecodeJump") } + + string get_opname_data() { result = this.getAChild("opname").getTextValue() } } diff --git a/python/tools/recorded-call-graph-metrics/src/cg_trace/generate_bytecode_expr_qll.py b/python/tools/recorded-call-graph-metrics/src/cg_trace/generate_bytecode_expr_qll.py new file mode 100644 index 00000000000..973c049d1fb --- /dev/null +++ b/python/tools/recorded-call-graph-metrics/src/cg_trace/generate_bytecode_expr_qll.py @@ -0,0 +1,46 @@ +import dataclasses +from typing import Any, List + +from cg_trace.bytecode_reconstructor import BytecodeExpr + +PREAMBLE = """\ +import python + +abstract class XMLBytecodeExpr extends XMLElement { } +""" + +CLASS_PREAMBLE = """\ +class XML{class_name} extends XMLBytecodeExpr {{ + XML{class_name}() {{ this.hasName("{class_name}") }} +""" + +CLASS_AFTER = """\ +} +""" + +ATTR_TEMPLATES = { + str: 'string get_{name}_data() {{ result = this.getAChild("{name}").getTextValue() }}', + int: 'int get_{name}_data() {{ result = this.getAChild("{name}").getTextValue().toInt() }}', + BytecodeExpr: 'XMLBytecodeExpr get_{name}_data() {{ result.getParent() = this.getAChild("{name}") }}', + List[ + BytecodeExpr + ]: 'XMLBytecodeExpr get_{name}_data(int index) {{ result = this.getAChild("{name}").getChild(index) }}', + Any: 'string get_{name}_data_raw() {{ result = this.getAChild("{name}").getTextValue() }}', +} + +if __name__ == "__main__": + + print(PREAMBLE) + + for sc in BytecodeExpr.__subclasses__(): + print(CLASS_PREAMBLE.format(class_name=sc.__name__)) + + for f in dataclasses.fields(sc): + field_template = ATTR_TEMPLATES.get(f.type) + if field_template: + generated = field_template.format(name=f.name) + print(f" {generated}") + else: + raise Exception("no template for", f.type) + + print(CLASS_AFTER)