Skip to content

krakjoe/inspector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Inspector

A disassembler and debug kit for PHP7

Build Status Coverage Status

Inspector provides an API for disassembling and debugging PHP7 code, in userland.

API

The following API is provided:

Note that, because of restrictions around an extension extending Reflection classes, Inspector classes that extend Reflection do so virtually with a __call interface.

namespace Inspector
{
	class InspectorClass extends \ReflectionClass {
		public function isPending() : bool;
		public function onResolve();

		public function getMethod(string name) : InspectorMethod;
		public function getMethods(int filter = 0) : array;

		public static function purge(array filters = []);
	}

	class InspectorMethod extends \ReflectionMethod implements InspectorInstructionInterface {
		public function getDeclaringClass() : InspectorClass;
	}

	class InspectorFunction extends \ReflectionFunction implements InspectorInstructionInterface {
		public function isPending() : bool;
		public function onResolve();
		public function onTrace(InspectorFrame $frame);

		public static function purge(array filters = []);
	}

	abstract class InspectorFile extends InspectorFunction {
		public function __construct(string file);

		public function isPending() : bool;
		public function onResolve();
		public function onTrace(InspectorFrame $frame);

		public static function purge(array filters = []);
	}

	interface InspectorInstructionInterface {
		public function getInstruction(int num = 0) : InspectorInstruction;
		public function getInstructionCount() : int;
		public function getEntryInstruction() : ?InspectorInstruction;
		public function findFirstInstruction(int opcode, int offset = 0) : ?InspectorInstruction;
		public function findLastInstruction(int opcode, int offset = -1) : ?InspectorInstruction;
		public function flushInstructionCache();
	}

	final class InspectorInstruction {
		public function getOffset() : int;
		public function getOpcode() : int;
		public function getOpcodeName() : ?string;
		public function getOperand(int which) : InspectorOperand;
		public function getExtendedValue() : mixed;
		public function getLine() : int;
		public function getFunction() : InspectorFunction;
		public function getNext() : ?InspectorInstruction;
		public function getPrevious() : ?InspectorInstruction;
		public function getRelative(int offset) : ?InspectorInstruction;
		public function getBreakPoint() : InspectorBreakPoint;

		public function getFlags([int which]) : ?int;

		/* opcode constants are registered with prefixed ZEND_ (verbatim) */
		/* vm constants are registered with prefix ZEND_VM_ (verbatim) */
	}

	final class InspectorOperand {
		const OP1;
		const OP2;
		const RESULT;

		public function isUnused() : bool;
		public function isExtendedTypeUnused() : bool;
		public function isCompiledVariable() : bool;
		public function isTemporaryVariable() : bool;
		public function isVariable() : bool;
		public function isConstant() : bool;
		public function isJumpTarget() : bool;
		public function getWhich() : int;
		public function getValue(?InspectorFrame $frame) : mixed;
		public function getName() : string;
		public function getNumber() : int;
		public function getInstruction() : InspectorInstruction;
	}

	abstract class InspectorBreakPoint extends InspectorBreakPointAbstract {
		public function __construct(InspectorInstruction opline);

		public function enable() : bool;
		public function disable() : bool;
		public function isEnabled() : bool;

		public function getInstruction() : InspectorInstruction;

		abstract public function hit(InspectorFrame frame);

		public static function onException(\Closure(InspectorFrame frame, \Throwable ex) handler);
	}

	final class InspectorFrame {
		public function getFunction() : InspectorInstructionInterface;
		public function getInstruction() : ?InspectorInstruction;
		public function setInstruction(InspectorInstruction instruction);
		public function getSymbols() : ?array;
		public function getPrevious() : ?InspectorFrame;
		public function getCall() : ?InspectorFrame;
		public function getStack() : array;
		public function getParameters() : array;
		public function getVariable(int num) : mixed;
		public function getThis() : ?object;

		public static function getCurrent() : InspectorFrame;
	}
}

Example

Other people are better at this than I am ...

Making stuff look nice is not my forte, all the same, here is some simple code using Inspector:

<?php
use Inspector\InspectorFunction;
use Inspector\InspectorInstruction;
use Inspector\InspectorOperand;

function printConstant($mixed) {
	if (strlen($mixed) > 8) {
		printf(
			"%s...\t", substr(str_replace(
			"\n",
			"\\n",
			$mixed
		), 0, 8));
	} else printf("%s\t", $mixed ?: "null");
}

function printOperand(InspectorOperand $op) {
	if ($op->isConstant()) {
		printConstant($op->getValue());
	} else if ($op->isCompiledVariable()) {
		printf("\$%s\t", $op->getName());
	} else if ($op->isTemporaryVariable()) {
		printf("T%d\t", $op->getNumber());
	} else if($op->isVariable()) {
		printf("V%d\t", $op->getNumber());
	} else printf("-\t");
}

function printFunction(InspectorFunction $inspector) {
	printf("OPCODE\t\tOP1\tOP2\tRESULT\n");
	$opline = $inspector->getInstruction();

	do {
		printf("%s\t", $opline->getOpcodeName());
		printOperand($opline->getOperand(InspectorOperand::OP1));
		printOperand($opline->getOperand(InspectorOperand::OP2));
		printOperand($opline->getOperand(InspectorOperand::RESULT));
		printf("\n");
	} while ($opline = $opline->getNext());
}

printFunction(new InspectorFunction(function($a, $b){
	return $a + $b;
}));

Which will yield:

OPCODE          OP1     OP2     RESULT
ZEND_RECV       -       -       $a
ZEND_RECV       -       -       $b
ZEND_ADD        $a      $b      T1
ZEND_RETURN     T1      -       -
ZEND_RETURN     null    -       -

TODO

  • tests (started)

About

Disassembler and Debug Kit for PHP 7

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages