Example #1
0
char *phpdbg_decode_opline(zend_op_array *ops, zend_op *opline) /*{{{ */
{
	const char *opcode_name = phpdbg_decode_opcode(opline->opcode);
	uint32_t flags = zend_get_opcode_flags(opline->opcode);
	char *result, *decode[4] = {NULL, NULL, NULL, NULL};

	/* EX */
	switch (opline->opcode) {
	case ZEND_FAST_CALL:
		if (opline->extended_value == ZEND_FAST_CALL_FROM_FINALLY) {
			decode[0] = estrdup("FAST_CALL<FROM_FINALLY>");
		}
		break;
	case ZEND_FAST_RET:
		if (opline->extended_value != 0) {
			spprintf(&decode[0], 0, "FAST_RET<%s>",
				opline->extended_value == ZEND_FAST_RET_TO_CATCH ? "TO_CATCH" : "TO_FINALLY");
		}
		break;
	}

	/* OP1 */
	decode[1] = phpdbg_decode_input_op(
		ops, opline, opline->op1, opline->op1_type, ZEND_VM_OP1_FLAGS(flags));

	/* OP2 */
	decode[2] = phpdbg_decode_input_op(
		ops, opline, opline->op2, opline->op2_type, ZEND_VM_OP2_FLAGS(flags));

	/* RESULT */
	switch (opline->opcode) {
	case ZEND_CATCH:
		spprintf(&decode[3], 0, "%" PRIu32, opline->result.num);
		break;
	default:
		decode[3] = phpdbg_decode_op(ops, &opline->result, opline->result_type);
		break;
	}

	spprintf(&result, 0,
		"%-23s %-20s %-20s %-20s",
		decode[0] ? decode[0] : opcode_name,
		decode[1] ? decode[1] : "",
		decode[2] ? decode[2] : "",
		decode[3] ? decode[3] : "");

	if (decode[0])
		efree(decode[0]);
	if (decode[1])
		efree(decode[1]);
	if (decode[2])
		efree(decode[2]);
	if (decode[3])
		efree(decode[3]);

	return result;
} /* }}} */
Example #2
0
char *phpdbg_decode_opline(zend_op_array *ops, zend_op *opline) /*{{{ */
{
	const char *opcode_name = phpdbg_decode_opcode(opline->opcode);
	uint32_t flags = zend_get_opcode_flags(opline->opcode);
	char *result, *decode[4] = {NULL, NULL, NULL, NULL};

	/* OpcodeName */
	if (opline->extended_value) {
		spprintf(&decode[0], 0, "%s<%" PRIi32 ">", opcode_name, opline->extended_value);
	}

	/* OP1 */
	decode[1] = phpdbg_decode_input_op(
		ops, opline, opline->op1, opline->op1_type, ZEND_VM_OP1_FLAGS(flags));

	/* OP2 */
	decode[2] = phpdbg_decode_input_op(
		ops, opline, opline->op2, opline->op2_type, ZEND_VM_OP2_FLAGS(flags));

	/* RESULT */
	switch (opline->opcode) {
	case ZEND_CATCH:
		spprintf(&decode[3], 0, "%" PRIu32, opline->result.num);
		break;
	default:
		decode[3] = phpdbg_decode_op(ops, &opline->result, opline->result_type);
		break;
	}

	spprintf(&result, 0,
		"%-23s %-20s %-20s %-20s",
		decode[0] ? decode[0] : opcode_name,
		decode[1] ? decode[1] : "",
		decode[2] ? decode[2] : "",
		decode[3] ? decode[3] : "");

	if (decode[0])
		efree(decode[0]);
	if (decode[1])
		efree(decode[1]);
	if (decode[2])
		efree(decode[2]);
	if (decode[3])
		efree(decode[3]);

	return result;
} /* }}} */
Example #3
0
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)");
			}
		}
	}
Example #4
0
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)");
			}
		}
	}