static void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, zend_uchar var_type, int var_num, uint32_t dump_flags) { if (ssa_var_num >= 0) { fprintf(stderr, "#%d.", ssa_var_num); } else { fprintf(stderr, "#?."); } zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : var_type), var_num); if (ssa_var_num >= 0 && ssa->vars) { if (ssa_var_num >= 0 && ssa->vars[ssa_var_num].no_val) { fprintf(stderr, " NOVAL"); } if (ssa->var_info) { zend_dump_ssa_var_info(ssa, ssa_var_num, dump_flags); if (ssa->var_info[ssa_var_num].has_range) { zend_dump_range(&ssa->var_info[ssa_var_num].range); } } } }
static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const void *data) { const char *name = zend_get_opcode_name(opline->opcode); uint32_t flags = zend_get_opcode_flags(opline->opcode); uint32_t n = 0; int len = 0; const zend_ssa *ssa = NULL; if (dump_flags & ZEND_DUMP_SSA) { ssa = (const zend_ssa*)data; } if (!b) { len = fprintf(stderr, "L%u (%u):", (uint32_t)(opline - op_array->opcodes), opline->lineno); } fprintf(stderr, "%*c", 12-len, ' '); if (!ssa || !ssa->ops || ssa->ops[opline - op_array->opcodes].result_use < 0) { if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops && ssa->ops[opline - op_array->opcodes].result_def >= 0) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def; zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags); } else { zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); } fprintf(stderr, " = "); } } if (name) { fprintf(stderr, "%s", (name + 5)); } else { fprintf(stderr, "OP_%d", (int)opline->opcode); } if (ZEND_VM_EXT_NUM == (flags & ZEND_VM_EXT_MASK)) { fprintf(stderr, " %u", opline->extended_value); } else if (ZEND_VM_EXT_DIM_OBJ == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_ASSIGN_DIM) { fprintf(stderr, " (dim)"); } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { fprintf(stderr, " (obj)"); } } else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case IS_NULL: fprintf(stderr, " (null)"); break; case IS_FALSE: fprintf(stderr, " (false)"); break; case IS_TRUE: fprintf(stderr, " (true)"); break; case IS_LONG: fprintf(stderr, " (long)"); break; case IS_DOUBLE: fprintf(stderr, " (double)"); break; case IS_STRING: fprintf(stderr, " (string)"); break; case IS_ARRAY: fprintf(stderr, " (array)"); break; case IS_OBJECT: fprintf(stderr, " (object)"); break; case IS_RESOURCE: fprintf(stderr, " (resource)"); break; case _IS_BOOL: fprintf(stderr, " (bool)"); break; case IS_CALLABLE: fprintf(stderr, " (callable)"); break; case IS_VOID: fprintf(stderr, " (void)"); break; default: fprintf(stderr, " (\?\?\?)"); break; } } else if (ZEND_VM_EXT_TYPE_MASK == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case (1<<IS_NULL): fprintf(stderr, " (null)"); break; case (1<<IS_FALSE): fprintf(stderr, " (false)"); break; case (1<<IS_TRUE): fprintf(stderr, " (true)"); break; case (1<<IS_LONG): fprintf(stderr, " (long)"); break; case (1<<IS_DOUBLE): fprintf(stderr, " (double)"); break; case (1<<IS_STRING): fprintf(stderr, " (string)"); break; case (1<<IS_ARRAY): fprintf(stderr, " (array)"); break; case (1<<IS_OBJECT): fprintf(stderr, " (object)"); break; case (1<<IS_RESOURCE): fprintf(stderr, " (resource)"); break; case ((1<<IS_FALSE)|(1<<IS_TRUE)): fprintf(stderr, " (bool)"); break; default: fprintf(stderr, " (\?\?\?)"); break; } } else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case ZEND_EVAL: fprintf(stderr, " (eval)"); break; case ZEND_INCLUDE: fprintf(stderr, " (include)"); break; case ZEND_INCLUDE_ONCE: fprintf(stderr, " (include_once)"); break; case ZEND_REQUIRE: fprintf(stderr, " (require)"); break; case ZEND_REQUIRE_ONCE: fprintf(stderr, " (require_once)"); break; default: fprintf(stderr, " (\?\?\?)"); break; } } else if (ZEND_VM_EXT_SRC == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_RETURNS_VALUE) { fprintf(stderr, " (value)"); } else if (opline->extended_value == ZEND_RETURNS_FUNCTION) { fprintf(stderr, " (function)"); } } else { if (ZEND_VM_EXT_VAR_FETCH & flags) { if (opline->extended_value & ZEND_FETCH_GLOBAL) { fprintf(stderr, " (global)"); } else if (opline->extended_value & ZEND_FETCH_LOCAL) { fprintf(stderr, " (local)"); } else if (opline->extended_value & ZEND_FETCH_GLOBAL_LOCK) { fprintf(stderr, " (global+lock)"); } } if (ZEND_VM_EXT_ISSET & flags) { if (!(opline->extended_value & ZEND_ISEMPTY)) { fprintf(stderr, " (isset)"); } else { fprintf(stderr, " (empty)"); } } if (ZEND_VM_EXT_ARRAY_INIT & flags) { fprintf(stderr, " %u", opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT); if (!(opline->extended_value & ZEND_ARRAY_NOT_PACKED)) { fprintf(stderr, " (packed)"); } } if (ZEND_VM_EXT_REF & flags) { if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) { fprintf(stderr, " (ref)"); } } }
static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const void *data) { const char *name = zend_get_opcode_name(opline->opcode); uint32_t flags = zend_get_opcode_flags(opline->opcode); uint32_t n = 0; int len = 0; const zend_ssa *ssa = NULL; if (dump_flags & ZEND_DUMP_SSA) { ssa = (const zend_ssa*)data; } if (!b) { len = fprintf(stderr, "L%u:", (uint32_t)(opline - op_array->opcodes)); } fprintf(stderr, "%*c", 8-len, ' '); if (!ssa || !ssa->ops || ssa->ops[opline - op_array->opcodes].result_use < 0) { if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def; ZEND_ASSERT(ssa_var_num >= 0); zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags); } else { zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); } fprintf(stderr, " = "); } } if (name) { fprintf(stderr, "%s", (name + 5)); } else { fprintf(stderr, "OP_%d", (int)opline->opcode); } if (ZEND_VM_EXT_NUM == (flags & ZEND_VM_EXT_MASK)) { fprintf(stderr, " %u", opline->extended_value); } else if (ZEND_VM_EXT_DIM_OBJ == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_ASSIGN_DIM) { fprintf(stderr, " (dim)"); } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { fprintf(stderr, " (obj)"); } } else if (ZEND_VM_EXT_CLASS_FETCH == (flags & ZEND_VM_EXT_MASK)) { zend_dump_class_fetch_type(opline->extended_value); } else if (ZEND_VM_EXT_CONST_FETCH == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value & IS_CONSTANT_UNQUALIFIED) { fprintf(stderr, " (unqualified)"); } if (opline->extended_value & IS_CONSTANT_CLASS) { fprintf(stderr, " (__class__)"); } if (opline->extended_value & IS_CONSTANT_IN_NAMESPACE) { fprintf(stderr, " (in-namespace)"); } } else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case IS_NULL: fprintf(stderr, " (null)"); break; case IS_FALSE: fprintf(stderr, " (false)"); break; case IS_TRUE: fprintf(stderr, " (true)"); break; case IS_LONG: fprintf(stderr, " (long)"); break; case IS_DOUBLE: fprintf(stderr, " (double)"); break; case IS_STRING: fprintf(stderr, " (string)"); break; case IS_ARRAY: fprintf(stderr, " (array)"); break; case IS_OBJECT: fprintf(stderr, " (object)"); break; case IS_RESOURCE: fprintf(stderr, " (resource)"); break; case _IS_BOOL: fprintf(stderr, " (bool)"); break; case IS_CALLABLE: fprintf(stderr, " (callable)"); break; case IS_VOID: fprintf(stderr, " (void)"); break; default: fprintf(stderr, " (\?\?\?)"); break; } } else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case ZEND_EVAL: fprintf(stderr, " (eval)"); break; case ZEND_INCLUDE: fprintf(stderr, " (include)"); break; case ZEND_INCLUDE_ONCE: fprintf(stderr, " (include_once)"); break; case ZEND_REQUIRE: fprintf(stderr, " (require)"); break; case ZEND_REQUIRE_ONCE: fprintf(stderr, " (require_once)"); break; default: fprintf(stderr, " (\?\?\?)"); break; } } else if (ZEND_VM_EXT_FAST_CALL == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_FAST_CALL_FROM_FINALLY) { fprintf(stderr, " (from-finally)"); } } else if (ZEND_VM_EXT_FAST_RET == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { fprintf(stderr, " (to-catch)"); } else if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { fprintf(stderr, " (to-finally)"); } } else if (ZEND_VM_EXT_SRC == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value == ZEND_RETURNS_VALUE) { fprintf(stderr, " (value)"); } else if (opline->extended_value == ZEND_RETURNS_FUNCTION) { fprintf(stderr, " (function)"); } } else if (ZEND_VM_EXT_SEND == (flags & ZEND_VM_EXT_MASK)) { if (opline->extended_value & ZEND_ARG_SEND_BY_REF) { fprintf(stderr, " (ref)"); } if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { fprintf(stderr, " (compile-time)"); } if (opline->extended_value & ZEND_ARG_SEND_FUNCTION) { fprintf(stderr, " (function)"); } if (opline->extended_value & ZEND_ARG_SEND_SILENT) { fprintf(stderr, " (silent)"); } } else { if (ZEND_VM_EXT_VAR_FETCH & flags) { switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: fprintf(stderr, " (global)"); break; case ZEND_FETCH_LOCAL: fprintf(stderr, " (local)"); break; case ZEND_FETCH_GLOBAL_LOCK: fprintf(stderr, " (global+lock)"); break; } } if (ZEND_VM_EXT_ISSET & flags) { if (opline->extended_value & ZEND_QUICK_SET) { fprintf(stderr, " (quick)"); } if (opline->extended_value & ZEND_ISSET) { fprintf(stderr, " (isset)"); } else if (opline->extended_value & ZEND_ISEMPTY) { fprintf(stderr, " (empty)"); } } if (ZEND_VM_EXT_ARG_NUM & flags) { fprintf(stderr, " %u", opline->extended_value & ZEND_FETCH_ARG_MASK); } if (ZEND_VM_EXT_ARRAY_INIT & flags) { fprintf(stderr, " %u", opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT); if (!(opline->extended_value & ZEND_ARRAY_NOT_PACKED)) { fprintf(stderr, " (packed)"); } } if (ZEND_VM_EXT_REF & flags) { if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) { fprintf(stderr, " (ref)"); } } }