Browse Source

merge from trunk

git-svn-id: svn://svn.lighttpd.net/xcache/branches/1.3@726 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
1.3
Xuefer 11 years ago
parent
commit
bd9466d6c8
  1. 2
      ChangeLog
  2. 259
      Decompiler.class.php
  3. 3
      Makefile.frag
  4. 2
      NEWS
  5. 11
      const_string_opcodes_php6.x.h
  6. 12
      coverager.c
  7. 36
      disassembler.c
  8. 4
      mkstructinfo.awk
  9. 5
      opcode_spec.c
  10. 42
      opcode_spec_def.h
  11. 1
      processor/hashtable.m4
  12. 43
      processor/head.m4
  13. 26
      processor/main.m4
  14. 199
      processor/processor.m4
  15. 25
      processor/struct.m4
  16. 76
      utils.c
  17. 21
      xcache.c
  18. 29
      xcache.h

2
ChangeLog

@ -1,5 +1,7 @@
1.3.2 2011-??-??
========
* disassembler: DECLARE_INHERITED_CLASS/DELAYED class not found
* disassembler: don't dump builtin functions
* fix win32 build against win32 native gnu tools
* compatibility fix: fix segv on shutdown when ionCube Loader is loaded
* fixed undefined index for xcache.count=1 and xcache.var_size>1

259
Decompiler.class.php

@ -27,17 +27,17 @@ function str($src, $indent = '') // {{{
*/
if (is_array($src)) {
die_error('array str');
$src = new Decompiler_Array($src, false, $indent);
exit('array str');
$src = new Decompiler_Array($src, $indent);
return $src->__toString();
}
if (is_object($src)) {
if (!method_exists($src, '__toString')) {
var_dump($src);
die_error('no __toString');
exit('no __toString');
}
return $src->__toString($indent);
return $src->__toString();
}
return $src;
@ -54,11 +54,14 @@ function value($value) // {{{
}
}
if (is_array($value)) {
$value = new Decompiler_Array($value, true);
if ($value instanceof Decompiler_Object) {
// use as is
}
else if (is_array($value)) {
$value = new Decompiler_Array($value);
}
else {
$value = new Decompiler_Value($value, true);
$value = new Decompiler_Value($value);
}
return $value;
}
@ -256,13 +259,11 @@ class Decompiler_ListBox extends Decompiler_Box // {{{
// }}}
class Decompiler_Array extends Decompiler_Value // {{{
{
var $needExport = false;
var $indent = '';
function Decompiler_Array($value = array(), $needexport = false, $indent = '')
function Decompiler_Array($value = array(), $indent = '')
{
$this->value = $value;
$this->needExport = $needexport;
$this->indent = $indent;
}
@ -285,7 +286,7 @@ class Decompiler_Array extends Decompiler_Value // {{{
}
++ $i;
}
if ($assoclen && $this->needExport) {
if ($assoclen) {
$assoclen += 2;
}
@ -305,9 +306,7 @@ class Decompiler_Array extends Decompiler_Value // {{{
}
}
if ($this->needExport) {
$k = var_export($k, true);
}
$k = var_export($k, true);
if ($multiline) {
$exp .= sprintf("%{$assoclen}s => ", $k);
}
@ -315,10 +314,7 @@ class Decompiler_Array extends Decompiler_Value // {{{
$exp .= $k . ' => ';
}
if (is_array($v)) {
$v = new Decompiler_Array($v, $this->needExport);
}
$exp .= str($v, $subindent);
$exp .= str(value($v), $subindent);
$i ++;
}
@ -432,22 +428,22 @@ class Decompiler
{
switch ($op['op_type']) {
case XC_IS_CONST:
return str(value($op['u.constant']));
return str(value($op['constant']));
case XC_IS_VAR:
case XC_IS_TMP_VAR:
$T = &$EX['Ts'];
$ret = $T[$op['u.var']];
$ret = $T[$op['var']];
if ($tostr) {
$ret = str($ret, $EX);
}
if ($free) {
unset($T[$op['u.var']]);
unset($T[$op['var']]);
}
return $ret;
case XC_IS_CV:
$var = $op['u.var'];
$var = $op['var'];
$var = $EX['op_array']['vars'][$var];
return '$' . $var['name'];
@ -456,6 +452,19 @@ class Decompiler
}
}
// }}}
function removeKeyPrefix($array, $prefix) // {{{
{
$prefixLen = strlen($prefix);
$ret = array();
foreach ($array as $key => $value) {
if (substr($key, 0, $prefixLen) == $prefix) {
$key = substr($key, $prefixLen);
}
$ret[$key] = $value;
}
return $ret;
}
// }}}
function &dop_array($op_array, $indent = '') // {{{
{
$opcodes = &$op_array['opcodes'];
@ -464,9 +473,37 @@ class Decompiler
unset($opcodes[$last]);
}
$EX['indent'] = '';
//for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
// $opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
//}
for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
if (function_exists('xcache_get_fixed_opcode')) {
$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
}
if (isset($opcodes[$i]['op1'])) {
$opcodes[$i]['op1'] = $this->removeKeyPrefix($opcodes[$i]['op1'], 'u.');
$opcodes[$i]['op2'] = $this->removeKeyPrefix($opcodes[$i]['op2'], 'u.');
$opcodes[$i]['result'] = $this->removeKeyPrefix($opcodes[$i]['result'], 'u.');
}
else {
$op = array(
'op1' => array(),
'op2' => array(),
'op3' => array(),
);
foreach ($opcodes[$i] as $name => $value) {
if (preg_match('!^(op1|op2|result)\\.(.*)!', $name, $m)) {
list(, $which, $field) = $m;
$op[$which][$field] = $value;
}
else if (preg_match('!^(op1|op2|result)_type$!', $name, $m)) {
list(, $which) = $m;
$op[$which]['op_type'] = $value;
}
else {
$op[$name] = $value;
}
}
$opcodes[$i] = $op;
}
}
// {{{ build jmp array
for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
$op = &$opcodes[$i];
@ -480,13 +517,13 @@ class Decompiler
$op['line'] = $i;
switch ($op['opcode']) {
case XC_JMP:
$target = $op['op1']['u.var'];
$target = $op['op1']['var'];
$op['jmpouts'] = array($target);
$opcodes[$target]['jmpins'][] = $i;
break;
case XC_JMPZNZ:
$jmpz = $op['op2']['u.opline_num'];
$jmpz = $op['op2']['opline_num'];
$jmpnz = $op['extended_value'];
$op['jmpouts'] = array($jmpz, $jmpnz);
$opcodes[$jmpz]['jmpins'][] = $i;
@ -500,7 +537,7 @@ class Decompiler
// case XC_FE_RESET:
case XC_FE_FETCH:
// case XC_JMP_NO_CTOR:
$target = $op['op2']['u.opline_num'];
$target = $op['op2']['opline_num'];
//if (!isset($target)) {
// $this->dumpop($op, $EX);
// var_dump($op); exit;
@ -538,6 +575,7 @@ class Decompiler
$EX['opcodes'] = &$opcodes;
// func call
$EX['object'] = null;
$EX['called_scope'] = null;
$EX['fbc'] = null;
$EX['argstack'] = array();
$EX['arg_types_stack'] = array();
@ -587,7 +625,7 @@ class Decompiler
}
if ($op['opcode'] == XC_FE_FETCH) {
$opline = $next;
$next = $op['op2']['u.opline_num'];
$next = $op['op2']['opline_num'];
$end = $next - 1;
ob_start();
@ -606,12 +644,12 @@ class Decompiler
}
/*
if ($op['opcode'] == XC_JMPZ) {
$target = $op2['u.opline_num'];
$target = $op2['opline_num'];
if ($line + 1) {
$nextblock = $EX['nextbbs'][$next];
$jmpop = end($nextblock);
if ($jmpop['opcode'] == XC_JMP) {
$ifendline = $op2['u.opline_num'];
$ifendline = $op2['opline_num'];
if ($ifendline >= $line) {
$cond = $op['cond'];
echo "{$indent}if ($cond) {\n";
@ -656,7 +694,7 @@ class Decompiler
default: continue 2;
}
$var = $fromop['result']['u.var'];
$var = $fromop['result']['var'];
var_dump($EX['Ts'][$var]);
$EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
}
@ -718,7 +756,7 @@ class Decompiler
// $this->dumpop($op, $EX); //var_dump($op);
$resvar = null;
if (($res['u.EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
if (isset($res['EA.type']) && ($res['EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
$istmpres = false;
}
else {
@ -748,8 +786,9 @@ class Decompiler
else {
switch ($opc) {
case XC_NEW: // {{{
array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
$EX['object'] = (int) $res['u.var'];
array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
$EX['object'] = (int) $res['var'];
$EX['called_scope'] = null;
$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
if (PHP_VERSION < 5) {
$resvar = '$new object$';
@ -764,10 +803,15 @@ class Decompiler
break;
case ZEND_FETCH_CLASS_PARENT:
$class = 'parent';
break;
case ZEND_FETCH_CLASS_STATIC:
$class = 'static';
break;
}
$istmpres = true;
}
else {
$class = $op2['u.constant'];
$class = $op2['constant'];
if (is_object($class)) {
$class = get_class($class);
}
@ -777,15 +821,15 @@ class Decompiler
// }}}
case XC_FETCH_CONSTANT: // {{{
if ($op1['op_type'] == XC_IS_CONST) {
$resvar = $op1['u.constant'];
$resvar = $op1['constant'];
}
else if ($op1['op_type'] == XC_IS_UNUSED) {
$resvar = $op2['u.constant'];
$resvar = $op2['constant'];
}
else {
$class = $T[$op1['u.var']];
$class = $T[$op1['var']];
assert($class[0] == 'class');
$resvar = $class[1] . '::' . $op2['u.constant'];
$resvar = $class[1] . '::' . $op2['constant'];
}
break;
// }}}
@ -798,7 +842,7 @@ class Decompiler
case XC_FETCH_IS:
case XC_UNSET_VAR:
$rvalue = $this->getOpVal($op1, $EX);
$fetchtype = $op2[PHP_VERSION < 5 ? 'u.fetch_type' : 'u.EA.type'];
$fetchtype = $op2[PHP_VERSION < 5 ? 'fetch_type' : 'EA.type'];
switch ($fetchtype) {
case ZEND_FETCH_STATIC_MEMBER:
$class = $this->getOpVal($op2, $EX);
@ -844,12 +888,12 @@ class Decompiler
$list = new Decompiler_List($this->getOpVal($op1, $EX, false));
$src = new Decompiler_ListBox($list);
if (!isset($op1['u.var'])) {
if (!isset($op1['var'])) {
$this->dumpop($op, $EX);
var_dump($op);
die('missing u.var');
die('missing var');
}
$T[$op1['u.var']] = $src;
$T[$op1['var']] = $src;
unset($list);
}
$dim = new Decompiler_Dim($src);
@ -889,7 +933,7 @@ class Decompiler
if (is_a($rvalue, 'Decompiler_ForeachBox')) {
$type = $rvalue->iskey ? 'fe_key' : 'fe_as';
$rvalue->obj[$type] = $lvalue;
unset($T[$op2['u.var']]);
unset($T[$op2['var']]);
break;
}
if (is_a($rvalue, "Decompiler_DimBox")) {
@ -975,7 +1019,7 @@ class Decompiler
else {
$rvalue = "${" . $rvalue . "}";
}
if ($op2['u.EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
$class = $this->getOpVal($op2, $EX);
$rvalue = $class . '::' . $rvalue;
}
@ -986,19 +1030,26 @@ class Decompiler
else {
$container = $this->getOpVal($op1, $EX);
$dim = $this->getOpVal($op2, $EX);
$rvalue = $container . "[$dim]";
if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) {
if (preg_match($this->rQuotedName, $dim)) {
$rvalue = $container . "->" . substr($dim, 1, -1);
}
else {
$rvalue = $container . "->{" . $dim . "}";
}
}
else {
$rvalue = $container . "[$dim]";
}
}
switch (PHP_VERSION < 5 ? $op['op2']['u.var'] /* u.constant */ : $ext) {
switch ((PHP_VERSION < 5 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
case ZEND_ISSET:
$rvalue = "isset($rvalue)";
break;
case ZEND_ISEMPTY:
$rvalue = "empty($rvalue)";
break;
default:
$this->dumpop($op, $EX);
die_error('1');
}
$resvar = $rvalue;
break;
@ -1011,29 +1062,38 @@ class Decompiler
$EX['argstack'][] = $ref . $this->getOpVal($op1, $EX);
break;
// }}}
case XC_INIT_STATIC_METHOD_CALL:
case XC_INIT_METHOD_CALL:
case XC_INIT_FCALL_BY_FUNC:
case XC_INIT_FCALL_BY_NAME: // {{{
if (($ext & ZEND_CTOR_CALL)) {
break;
}
array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
if ($opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
$obj = $this->getOpVal($op1, $EX);
if (!isset($obj)) {
$obj = '$this';
}
$EX['object'] = $obj;
if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) {
$EX['object'] = null;
$EX['called_scope'] = $this->unquoteName($obj);
}
else {
$EX['object'] = $obj;
$EX['called_scope'] = null;
}
if ($res['op_type'] != XC_IS_UNUSED) {
$resvar = '$obj call$';
}
}
else {
$EX['object'] = null;
$EX['called_scope'] = null;
}
if ($opc == XC_INIT_FCALL_BY_FUNC) {
$which = $op1['u.var'];
$which = $op1['var'];
$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
}
else {
@ -1042,7 +1102,7 @@ class Decompiler
break;
// }}}
case XC_DO_FCALL_BY_FUNC:
$which = $op1['u.var'];
$which = $op1['var'];
$fname = $EX['op_array']['funcs'][$which]['name'];
$args = $this->popargs($EX, $ext);
$resvar = $fname . "($args)";
@ -1064,6 +1124,7 @@ class Decompiler
$resvar =
(isset($object) ? $object . '->' : '' )
. (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' )
. $fname . "($args)";
unset($args);
@ -1071,23 +1132,25 @@ class Decompiler
$T[$EX['object']] = $resvar;
$resvar = null;
}
list($EX['object'], $EX['fbc']) = array_pop($EX['arg_types_stack']);
list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']);
break;
// }}}
case XC_VERIFY_ABSTRACT_CLASS: // {{{
//unset($T[$op1['u.var']]);
//unset($T[$op1['var']]);
break;
// }}}
case XC_DECLARE_CLASS:
case XC_DECLARE_INHERITED_CLASS: // {{{
$key = $op1['u.constant'];
$class = &$this->dc['class_table'][$key];
if (!isset($class)) {
echo 'class not found: ' . $key;
case XC_DECLARE_INHERITED_CLASS:
case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{
$key = $op1['constant'];
if (!isset($this->dc['class_table'][$key])) {
echo 'class not found: ', $key, 'existing classes are:', "\n";
var_dump(array_keys($this->dc['class_table']));
exit;
}
$class = &$this->dc['class_table'][$key];
$class['name'] = $this->unquoteName($this->getOpVal($op2, $EX));
if ($opc == XC_DECLARE_INHERITED_CLASS) {
if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) {
$ext /= XC_SIZEOF_TEMP_VARIABLE;
$class['parent'] = $T[$ext];
unset($T[$ext]);
@ -1098,7 +1161,7 @@ class Decompiler
while ($i + 2 < $ic
&& $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
&& $opcodes[$i + 2]['op1']['u.var'] == $res['u.var']
&& $opcodes[$i + 2]['op1']['var'] == $res['var']
&& $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
$fetchop = &$opcodes[$i + 1];
$impl = $this->unquoteName($this->getOpVal($fetchop['op2'], $EX));
@ -1164,10 +1227,10 @@ class Decompiler
if ($opc == XC_ADD_ARRAY_ELEMENT) {
$offset = $this->getOpVal($op2, $EX);
if (isset($offset)) {
$T[$res['u.var']]->value[$offset] = $rvalue;
$T[$res['var']]->value[$offset] = $rvalue;
}
else {
$T[$res['u.var']]->value[] = $rvalue;
$T[$res['var']]->value[] = $rvalue;
}
}
else {
@ -1201,7 +1264,7 @@ class Decompiler
break;
// }}}
case XC_INCLUDE_OR_EVAL: // {{{
$type = $op2['u.var']; // hack
$type = $op2['var']; // hack
$keyword = $this->includeTypes[$type];
$resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")";
break;
@ -1214,7 +1277,7 @@ class Decompiler
$op['fe_src'] = $this->getOpVal($op1, $EX);
$fe = new Decompiler_ForeachBox($op);
$fe->iskey = false;
$T[$res['u.var']] = $fe;
$T[$res['var']] = $fe;
++ $i;
if (($ext & ZEND_FE_FETCH_WITH_KEY)) {
@ -1222,21 +1285,21 @@ class Decompiler
$fe->iskey = true;
$res = $opcodes[$i]['result'];
$T[$res['u.var']] = $fe;
$T[$res['var']] = $fe;
}
break;
// }}}
case XC_SWITCH_FREE: // {{{
// unset($T[$op1['u.var']]);
// unset($T[$op1['var']]);
break;
// }}}
case XC_FREE: // {{{
$free = $T[$op1['u.var']];
$free = $T[$op1['var']];
if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) {
$op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')');
$lastphpop = &$op;
}
unset($T[$op1['u.var']], $free);
unset($T[$op1['var']], $free);
break;
// }}}
case XC_JMP_NO_CTOR:
@ -1259,10 +1322,11 @@ class Decompiler
unset($op['cond_true']);
}
if (isset($op['cond_false'])) {
echo "TODO(cond_false):\n";
var_dump($op);// exit;
}
if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
$targetop = &$EX['opcodes'][$op2['u.opline_num']];
$targetop = &$EX['opcodes'][$op2['opline_num']];
if ($opc == XC_JMPNZ_EX) {
$targetop['cond_true'][] = str($rvalue);
}
@ -1290,7 +1354,7 @@ class Decompiler
$offset = $this->getOpVal($op1, $EX);
$lvalue = $this->getOpVal($op['result'], $EX);
if ($opc == XC_RECV_INIT) {
$default = value($op['op2']['u.constant']);
$default = value($op['op2']['constant']);
}
else {
$default = null;
@ -1376,8 +1440,8 @@ class Decompiler
}
if (isset($resvar)) {
if ($istmpres) {
$T[$res['u.var']] = $resvar;
$lastresvar = &$T[$res['u.var']];
$T[$res['var']] = $resvar;
$lastresvar = &$T[$res['var']];
}
else {
$op['php'] = $resvar;
@ -1423,18 +1487,18 @@ class Decompiler
foreach (array('op1' => 'op1', 'op2' => 'op2', 'result' => 'res') as $k => $kk) {
switch ($op[$k]['op_type']) {
case XC_IS_UNUSED:
$d[$kk] = '*UNUSED* ' . $op[$k]['u.opline_num'];
$d[$kk] = '*UNUSED* ' . $op[$k]['opline_num'];
break;
case XC_IS_VAR:
$d[$kk] = '$' . $op[$k]['u.var'];
$d[$kk] = '$' . $op[$k]['var'];
if ($kk != 'res') {
$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
}
break;
case XC_IS_TMP_VAR:
$d[$kk] = '#' . $op[$k]['u.var'];
$d[$kk] = '#' . $op[$k]['var'];
if ($kk != 'res') {
$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
}
@ -1607,8 +1671,8 @@ class Decompiler
// {{{ properties
if (!empty($class['default_properties'])) {
echo "\n";
$infos = empty($class['properties_info']) ? null : $class['properties_info'];
foreach ($class['default_properties'] as $name => $v) {
$infos = !empty($class['properties_info']) ? $class['properties_info'] : null;
foreach (!empty($class['properties_info']) ? $class['properties_info'] : ($class['default_static_members'] + $class['default_properties']) as $name => $dummy) {
$info = (isset($infos) && isset($infos[$name])) ? $infos[$name] : null;
if (isset($info)) {
if (!empty($info['doc_comment'])) {
@ -1619,6 +1683,21 @@ class Decompiler
}
echo $newindent;
$static = false;
if (isset($info)) {
if ($info['flags'] & ZEND_ACC_STATIC) {
$static = true;
}
}
else if (isset($class['default_static_members'][$name])) {
$static = true;
}
if ($static) {
echo "static ";
}
$mangled = false;
if (PHP_VERSION < 5) {
echo 'var ';
}
@ -1635,20 +1714,23 @@ class Decompiler
break;
case ZEND_ACC_PRIVATE:
echo "private ";
$mangled = true;
break;
case ZEND_ACC_PROTECTED:
echo "protected ";
$mangled = true;
break;
}
if ($info['flags'] & ZEND_ACC_STATIC) {
echo "static ";
}
}
echo '$', $name;
if (isset($v)) {
$key = isset($info) ? $info['name'] . ($mangled ? "\000" : "") : $name;
$value = $class[$static ? 'default_static_members' : 'default_properties'][$key];
if (isset($value)) {
echo ' = ';
echo str(value($v));
echo str(value($value));
}
echo ";\n";
}
@ -1786,6 +1868,7 @@ define('ZEND_FETCH_CLASS_MAIN', 3);
define('ZEND_FETCH_CLASS_GLOBAL', 4);
define('ZEND_FETCH_CLASS_AUTO', 5);
define('ZEND_FETCH_CLASS_INTERFACE', 6);
define('ZEND_FETCH_CLASS_STATIC', 7);
define('ZEND_EVAL', (1<<0));
define('ZEND_INCLUDE', (1<<1));
@ -1851,10 +1934,12 @@ foreach (array (
'XC_ISSET_ISEMPTY_DIM_OBJ' => -1,
'XC_ISSET_ISEMPTY_PROP_OBJ' => -1,
'XC_ISSET_ISEMPTY_VAR' => -1,
'XC_INIT_STATIC_METHOD_CALL' => -1,
'XC_INIT_METHOD_CALL' => -1,
'XC_VERIFY_ABSTRACT_CLASS' => -1,
'XC_DECLARE_CLASS' => -1,
'XC_DECLARE_INHERITED_CLASS' => -1,
'XC_DECLARE_INHERITED_CLASS_DELAYED' => -1,
'XC_ADD_INTERFACE' => -1,
'XC_POST_DEC_OBJ' => -1,
'XC_POST_INC_OBJ' => -1,

3
Makefile.frag

@ -31,6 +31,9 @@ processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/processor.c
$(builddir)/disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
$(builddir)/opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/opcode_spec.c $(srcdir)/opcode_spec_def.h $(srcdir)/const_string.h
opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/opcode_spec.c $(srcdir)/opcode_spec_def.h $(srcdir)/const_string.h
$(builddir)/xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h $(srcdir)/utils.h
xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h $(srcdir)/utils.h

2
NEWS

@ -1,5 +1,7 @@
1.3.2 2011-??-??
========
* memory leak on recompile
* disassembler fixes and updates for new PHP
* win32 build fix
* improve compatibility with ionCube Loader

11
const_string_opcodes_php6.x.h

@ -1,4 +1,4 @@
/* size = 154 */
/* size = 157 */
static const char *const xc_opcode_names[] = {
/* 0 */ "NOP",
/* 1 */ "ADD",
@ -111,7 +111,7 @@ static const char *const xc_opcode_names[] = {
/* 108 */ "THROW",
/* 109 */ "FETCH_CLASS",
/* 110 */ "CLONE",
/* 111 */ "UNDEF",
/* 111 */ "RETURN_BY_REF",
/* 112 */ "INIT_METHOD_CALL",
/* 113 */ "INIT_STATIC_METHOD_CALL",
/* 114 */ "ISSET_ISEMPTY_VAR",
@ -151,7 +151,10 @@ static const char *const xc_opcode_names[] = {
/* 148 */ "ISSET_ISEMPTY_PROP_OBJ",
/* 149 */ "HANDLE_EXCEPTION",
/* 150 */ "USER_OPCODE",
/* 151 */ "U_NORMALIZE",
/* 151 */ "UNDEF",
/* 152 */ "JMP_SET",
/* 153 */ "DECLARE_LAMBDA_FUNCTION"
/* 153 */ "DECLARE_LAMBDA_FUNCTION",
/* 154 */ "ADD_TRAIT",
/* 155 */ "BIND_TRAITS",
/* 156 */ "SEPARATE"
};

12
coverager.c

@ -378,25 +378,23 @@ static void xc_coverager_add_hits(HashTable *cov, long line, long hits TSRMLS_DC
static int xc_coverager_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */
{
zend_uint size;
size = op_array->size;
zend_uint last = op_array->last;
do {
next_op:
if (size == 0) {
if (last == 0) {
break;
}
switch (op_array->opcodes[size - 1].opcode) {
switch (op_array->opcodes[last - 1].opcode) {
#ifdef ZEND_HANDLE_EXCEPTION
case ZEND_HANDLE_EXCEPTION:
#endif
case ZEND_RETURN:
case ZEND_EXT_STMT:
size --;
--last;
goto next_op;
}
} while (0);
return size;
return last;
}
/* }}} */

36
disassembler.c

@ -5,17 +5,23 @@
#define return_value dst
/* sandbox {{{ */
#undef TG
#undef OG
#define TG(x) (sandbox->tmp_##x)
#define OG(x) (sandbox->orig_##x)
/* }}} */
#ifndef HAVE_XCACHE_OPCODE_SPEC_DEF
#error disassembler cannot be built without xcache/opcode_spec_def.h
#endif
static void xc_dasm(zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
static void xc_dasm(xc_sandbox_t *sandbox, zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
{
Bucket *b;
zval *zv, *list;
xc_compile_result_t cr;
int bufsize = 2;
char *buf;
int keysize;
xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
@ -32,13 +38,23 @@ static void xc_dasm(zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
ALLOC_INIT_ZVAL(list);
array_init(list);
xc_dasm_HashTable_zend_function(list, CG(function_table) TSRMLS_CC);
b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
for (; b; b = b->pListNext) {
ALLOC_INIT_ZVAL(zv);
array_init(zv);
xc_dasm_zend_function(zv, b->pData TSRMLS_CC);
add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, zv);
}
add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
buf = emalloc(bufsize);
ALLOC_INIT_ZVAL(list);
array_init(list);
for (b = CG(class_table)->pListHead; b; b = b->pListNext) {
b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
for (; b; b = b->pListNext) {
int keysize, keyLength;
ALLOC_INIT_ZVAL(zv);
array_init(zv);
xc_dasm_zend_class_entry(zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
@ -52,20 +68,20 @@ static void xc_dasm(zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
}
memcpy(buf, BUCKET_KEY_S(b), keysize);
buf[keysize - 2] = buf[keysize - 1] = ""[0];
keysize = b->nKeyLength;
keyLength = b->nKeyLength;
#ifdef IS_UNICODE
if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
if (buf[0] == ""[0] && buf[1] == ""[0]) {
keysize ++;
keyLength ++;
}
} else
#endif
{
if (buf[0] == ""[0]) {
keysize ++;
keyLength ++;
}
}
add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), b->nKeyLength, zv);
add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
}
efree(buf);
add_assoc_zval_ex(dst, ZEND_STRS("class_table"), list);
@ -96,7 +112,7 @@ void xc_dasm_string(zval *dst, zval *source TSRMLS_DC) /* {{{ */
goto err_compile;
}
xc_dasm(dst, op_array TSRMLS_CC);
xc_dasm(&sandbox, dst, op_array TSRMLS_CC);
/* free */
efree(eval_name);
@ -141,7 +157,7 @@ void xc_dasm_file(zval *dst, const char *filename TSRMLS_DC) /* {{{ */
goto err_compile;
}
xc_dasm(dst, op_array TSRMLS_CC);
xc_dasm(&sandbox, dst, op_array TSRMLS_CC);
/* free */
#ifdef ZEND_ENGINE_2

4
mkstructinfo.awk

@ -49,10 +49,10 @@ incomment {
sizeinfo = sizeinfo "sizeof(((" instruct "*)NULL)->" buffer[i] ")";
if (i == 0) {
elms = buffer[i];
elms = "\"" buffer[i] "\"";
}
else {
elms = elms "," buffer[i];
elms = elms "," "\"" buffer[i] "\"";
}
}
printf "define(`ELEMENTSOF_%s', `%s')\n", instruct, elms;

5
opcode_spec.c

@ -19,6 +19,11 @@ zend_uchar xc_get_opcode_spec_count()
const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode)
{
#ifndef NDEBUG
if (xc_get_opcode_count() != xc_get_opcode_spec_count()) {
fprintf(stderr, "count mismatch: xc_get_opcode_count=%d, xc_get_opcode_spec_count=%d\n", xc_get_opcode_count(), xc_get_opcode_spec_count());
}
#endif
assert(xc_get_opcode_count() == xc_get_opcode_spec_count());
assert(opcode < xc_get_opcode_spec_count());
return &xc_opcode_spec[opcode];

42
opcode_spec_def.h

@ -103,7 +103,7 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
OPSPEC( UNUSED, STD, UNUSED, VAR)
#endif
#ifdef ZEND_ENGINE_2_3
OPSPEC( STD, STD, STD, STD) /* 69 INIT_NS_FCALL_BY_NAME */
OPSPEC( STD, STD, STD, UNUSED) /* 69 INIT_NS_FCALL_BY_NAME */
#else
OPSPEC( UNUSED, STD, OPLINE, UNUSED) /* 69 JMP_NO_CTOR */
#endif
@ -146,13 +146,16 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
OPSPEC( UNUSED, VAR, STD, VAR) /* 96 FETCH_DIM_UNSET */
OPSPEC( UNUSED, VAR_2, STD, VAR) /* 97 FETCH_OBJ_UNSET */
OPSPEC( UNUSED, STD, STD, VAR) /* 98 FETCH_DIM_TMP_VAR */
#ifdef ZEND_ENGINE_2
OPSPEC( UNUSED, UCLASS, STD, TMP) /* 99 FETCH_CONSTANT */
#else
OPSPEC( UNUSED, STD, UNUSED, TMP) /* 99 FETCH_CONSTANT */
#endif
#ifdef ZEND_ENGINE_2_3
OPSPEC( STD, JMPADDR, STD, UNUSED) /* 100 GOTO */
#else
OPSPEC( DECLARE, STD, STD, UNUSED) /* 100 DECLARE_FUNCTION_OR_CLASS */
#endif
OPSPEC( STD, STD, STD, STD) /* 101 EXT_STMT */
OPSPEC( STD, STD, STD, STD) /* 102 EXT_FCALL_BEGIN */
OPSPEC( STD, STD, STD, STD) /* 103 EXT_FCALL_END */
@ -164,11 +167,18 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
OPSPEC( UNUSED, STD, OPLINE, UNUSED) /* 108 THROW */
OPSPEC( FCLASS, STD, STD, CLASS) /* 109 FETCH_CLASS */
OPSPEC( UNUSED, STD, UNUSED, VAR) /* 110 CLONE */
OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 111 INIT_CTOR_CALL */
OPSPEC( UNUSED, STD, STD, VAR) /* 112 INIT_METHOD_CALL */
# ifdef ZEND_ENGINE_2_3
OPSPEC( UNUSED, STD, STD, UNUSED) /* 113 INIT_STATIC_METHOD_CALL */
# else
OPSPEC( UNUSED, UCLASS, STD, UNUSED) /* 113 INIT_STATIC_METHOD_CALL */
# endif
OPSPEC( ISSET, STD, FETCH, TMP) /* 114 ISSET_ISEMPTY_VAR */
OPSPEC( ISSET, STD, STD, TMP) /* 115 ISSET_ISEMPTY_DIM_OBJ */
OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 116 IMPORT_FUNCTION */
OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 117 IMPORT_CLASS */
OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 118 IMPORT_CONST */
@ -185,6 +195,7 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
OPSPEC( UNUSED, STD, STD, VAR) /* 129 ASSIGN_BW_OR_OBJ */
OPSPEC( UNUSED, STD, STD, VAR) /* 130 ASSIGN_BW_AND_OBJ */
OPSPEC( UNUSED, STD, STD, VAR) /* 131 ASSIGN_BW_XOR_OBJ */
OPSPEC( UNUSED, STD, STD, VAR) /* 132 PRE_INC_OBJ */
OPSPEC( UNUSED, STD, STD, VAR) /* 133 PRE_DEC_OBJ */
OPSPEC( UNUSED, STD, STD, TMP) /* 134 POST_INC_OBJ */
@ -199,19 +210,38 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
#ifdef ZEND_ENGINE_2_3
OPSPEC( DECLARE, STD, STD, UNUSED) /* 143 DECLARE_CONST */
#else
OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 143 START_NAMESPACE */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 143 UNDEF-143 */
#endif
#ifdef ZEND_ENGINE_2_3
OPSPEC( IFACE, CLASS, STD, UNUSED) /* 144 ADD_INTERFACE */
#else
OPSPEC( IFACE, CLASS, CLASS, UNUSED) /* 144 ADD_INTERFACE */
#endif
#ifdef ZEND_ENGINE_2_3
OPSPEC( CLASS, STD, STD, OPLINE) /* 145 DECLARE_INHERITED_CLASS_DELAYED */
#else
OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 145 VERIFY_INSTANCEOF */
#endif
OPSPEC( UNUSED, CLASS, UNUSED, UNUSED) /* 146 VERIFY_ABSTRACT_CLASS */
OPSPEC( UNUSED, STD, STD, VAR) /* 147 ASSIGN_DIM */
OPSPEC( ISSET, STD, STD, TMP) /* 148 ISSET_ISEMPTY_PROP_OBJ */
OPSPEC( STD, UNUSED, UNUSED, STD) /* 149 HANDLE_EXCEPTION */
OPSPEC( STD, UNUSED, UNUSED, STD) /* 150 USER_OPCODE */
# ifdef ZEND_ENGINE_2_3
OPSPEC( STD, UNUSED, UNUSED, STD) /* 150 ZEND_USER_OPCODE */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 151 UNDEF */
OPSPEC( UNUSED, STD, JMPADDR, UNUSED) /* 152 JMP_SET */
OPSPEC( UNUSED, STD, STD, UNUSED) /* 153 DECLARE_LAMBDA_FUNCTION */
OPSPEC( UNUSED, STD, JMPADDR, TMP) /* 152 JMP_SET */
OPSPEC( UNUSED, STD, STD, TMP) /* 153 DECLARE_LAMBDA_FUNCTION */
# else
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 151 UNDEF */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 152 UNDEF */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 153 UNDEF */
# endif
#else
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 107 UNDEF */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 108 UNDEF */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 109 UNDEF */
OPSPEC( FCALL, STD, OPLINE, VAR) /* 61 DO_FCALL_BY_FUNC */
OPSPEC(INIT_FCALL, STD, STD, UNUSED) /* 111 INIT_FCALL_BY_FUNC */
OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 112 UNDEF */
#endif
};

1
processor/hashtable.m4

@ -64,7 +64,6 @@ define(`DEF_HASH_TABLE_FUNC', `
')
efree(buf);
return; /* no check size */
', `
dnl }}}
Bucket *b, *pnew = NULL, *prev = NULL;

43
processor/head.m4

@ -298,6 +298,49 @@ static void xc_zend_extension_op_array_ctor_handler(zend_extension *extension, z
}
}
/* }}} */
/* {{{ field name checker */
IFASSERT(`dnl
int xc_check_names(const char *file, int line, const char *functionName, const char **assert_names, int assert_names_count, HashTable *done_names)
{
int errors = 0;
if (assert_names_count) {
int i;
Bucket *b;
for (i = 0; i < assert_names_count; ++i) {
if (!zend_hash_exists(done_names, assert_names[i], strlen(assert_names[i]) + 1)) {
fprintf(stderr
, "missing field at %s `#'%d %s`' : %s\n"
, file, line, functionName
, assert_names[i]
);
++errors;
}
}
for (b = done_names->pListHead; b != NULL; b = b->pListNext) {
int known = 0;
int i;
for (i = 0; i < assert_names_count; ++i) {
if (strcmp(assert_names[i], BUCKET_KEY_S(b)) == 0) {
known = 1;
break;
}
}
if (!known) {
fprintf(stderr
, "unknown field at %s `#'%d %s`' : %s\n"
, file, line, functionName
, BUCKET_KEY_S(b)
);
++errors;
}
}
}
return errors;
}
')
/* }}} */
dnl ================ export API
/* export: xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC); :export {{{ */
xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC) {

26
processor/main.m4

@ -163,15 +163,6 @@ define(`COPYNULL_EX', `
')
dnl }}}
dnl {{{ COPYNULL(1:elm)
# foreach(VAR, (LIST), STMT)
m4_define([foreach],
[m4_pushdef([$1])_foreach([$1], [$2], [$3])m4_popdef([$1])])
m4_define([_arg1], [$1])
m4_define([_foreach],
[ifelse([$2], [()], ,
[m4_define([$1], _arg1$2)$3[]_foreach([$1],
(shift$2),
[$3])])])
define(`COPYNULL', `
COPYNULL_EX(`dst->$1', `$2')DONE(`$1')
')
@ -194,12 +185,25 @@ foreach(`i', `($1)', `popdef(`item_'defn(`i'))')dnl
')
dnl }}}
dnl {{{ DONE_*
define(`DONE_SIZE', `IFASSERT(`
define(`DONE_SIZE', `IFASSERT(`dnl
done_size += $1`';
done_count ++;
')')
define(`DONE', `
define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,$1')
define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,"$1"')
IFASSERT(`dnl
if (zend_hash_exists(&done_names, "$1", sizeof("$1"))) {
fprintf(stderr
, "duplicate field at %s `#'%d FUNC_NAME`' : %s\n"
, __FILE__, __LINE__
, "$1"
);
}
else {
zend_uchar b = 1;
zend_hash_add(&done_names, "$1", sizeof("$1"), (void*)&b, sizeof(b), NULL);
}
')
DONE_SIZE(`sizeof(src->$1)')
')
define(`DISABLECHECK', `

199
processor/processor.m4

@ -84,7 +84,6 @@ DEF_STRUCT_P_FUNC(`zval', , `dnl {{{
DONE(refcount)
#endif
} while(0);
return;
', `
dnl IFDASM else
/* Variable information */
@ -222,11 +221,17 @@ DEF_STRUCT_P_FUNC(`zend_arg_info', , `
PROC_ZSTRING_L(, name, name_len)
DISPATCH(zend_uint, class_name_len)
PROC_ZSTRING_L(, class_name, class_name_len)
#ifdef ZEND_ENGINE_2_4
DISPATCH(zend_uchar, type_hint)
#else
DISPATCH(zend_bool, array_type_hint)
#endif
DISPATCH(zend_bool, allow_null)
DISPATCH(zend_bool, pass_by_reference)
#ifndef ZEND_ENGINE_2_4
DISPATCH(zend_bool, return_reference)
DISPATCH(int, required_num_args)
#endif
')
#endif
dnl }}}
@ -272,6 +277,9 @@ DEF_STRUCT_P_FUNC(`zend_property_info', , `
DISPATCH(int, name_length)
PROC_ZSTRING_L(, name, name_length)
DISPATCH(ulong, h)
#ifdef ZEND_ENGINE_2_4
DISPATCH(int, offset)
#endif
#ifdef ZEND_ENGINE_2_1
DISPATCH(int, doc_comment_len)
PROC_ZSTRING_L(, doc_comment, doc_comment_len)
@ -284,6 +292,7 @@ DEF_STRUCT_P_FUNC(`zend_property_info', , `
#endif
dnl }}}
DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
int i;
IFCALCCOPY(`
processor->active_class_entry_src = src;
IFCOPY(`processor->active_class_entry_dst = dst;')
@ -306,33 +315,59 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
#else
STRUCT_P(int, refcount)
#endif
#ifndef ZEND_ENGINE_2_4
DISPATCH(zend_bool, constants_updated)
#endif
#ifdef ZEND_ENGINE_2
DISPATCH(zend_uint, ce_flags)
#endif
STRUCT(HashTable, default_properties, HashTable_zval_ptr)
#ifdef ZEND_ENGINE_2_4
DISPATCH(int, default_properties_count)
STRUCT_ARRAY(default_properties_count, zval, default_properties_table)
DISPATCH(int, default_static_members_count)
STRUCT_ARRAY(default_static_members_count, zval, default_static_members_table)
IFCOPY(`dst->static_members_table = &dst->default_static_members_table;')
DONE(static_members_table)
#else
IFCOPY(`dst->builtin_functions = src->builtin_functions;')
DONE(builtin_functions)
#ifdef ZEND_ENGINE_2
STRUCT(HashTable, default_properties, HashTable_zval_ptr)
# ifdef ZEND_ENGINE_2
STRUCT(HashTable, properties_info, HashTable_zend_property_info)
# ifdef ZEND_ENGINE_2_1
# ifdef ZEND_ENGINE_2_1
STRUCT(HashTable, default_static_members, HashTable_zval_ptr)
IFCOPY(`dst->static_members = &dst->default_static_members;')
DONE(static_members)
# else
# else
STRUCT_P(HashTable, static_members, HashTable_zval_ptr)
# endif
# endif
#endif /* ZEND_ENGINE_2_4 */
#ifdef ZEND_ENGINE_2
STRUCT(HashTable, constants_table, HashTable_zval_ptr)
dnl runtime binding: ADD_INTERFACE will deal with it
dnl runtime binding: ADD_TRAIT will deal with it
IFRESTORE(`
if (src->num_interfaces) {
CALLOC(dst->interfaces, zend_class_entry*, src->num_interfaces)
DONE(`interfaces')
# ifdef ZEND_ENGINE_2_4
CALLOC(dst->traits, zend_class_entry*, src->num_traits)
DONE(`traits')
DONE(`trait_aliases')
DONE(`trait_precedences')
# endif
}
else {
COPYNULL(interfaces)
COPYNULL(`interfaces')
# ifdef ZEND_ENGINE_2_4
COPYNULL(`traits')
COPYNULL(`trait_aliases')
COPYNULL(`trait_precedences')
# endif
}
')
IFDASM(`
@ -349,25 +384,55 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
add_assoc_zval_ex(dst, ZEND_STRS("interfaces"), arr);
*/
DONE(`interfaces')
# ifdef ZEND_ENGINE_2_4
DONE(`traits')
DONE(`trait_aliases')
DONE(`trait_precedences')
# endif
}
else {
COPYNULL(interfaces)
COPYNULL(`interfaces')
# ifdef ZEND_ENGINE_2_4
COPYNULL(`traits')
COPYNULL(`trait_aliases')
COPYNULL(`trait_precedences')
# endif
}
')
IFRESTORE(`', `
IFDASM(`', `
DONE(`interfaces')
# ifdef ZEND_ENGINE_2_4
DONE(`traits')
DONE(`trait_aliases')
DONE(`trait_precedences')
# endif
')
')
DISPATCH(zend_uint, num_interfaces)
# ifdef ZEND_ENGINE_2_4
DISPATCH(zend_uint, num_traits)
# endif
# ifdef ZEND_ENGINE_2_4
DISABLECHECK(`
IFRESTORE(`COPY(info.user.filename)', `PROC_STRING(info.user.filename)')
DISPATCH(zend_uint, info.user.line_start)
DISPATCH(zend_uint, info.user.line_end)
DISPATCH(zend_uint, info.user.doc_comment_len)
PROC_ZSTRING_L(, info.user.doc_comment, info.user.doc_comment_len)
')
DONE(info)
# else
IFRESTORE(`COPY(filename)', `PROC_STRING(filename)')
DISPATCH(zend_uint, line_start)
DISPATCH(zend_uint, line_end)
#ifdef ZEND_ENGINE_2_1
# ifdef ZEND_ENGINE_2_1
DISPATCH(zend_uint, doc_comment_len)
PROC_ZSTRING_L(, doc_comment, doc_comment_len)
#endif
# endif
# endif
/* # NOT DONE */
COPY(serialize_func)
COPY(unserialize_func)
@ -375,9 +440,9 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
COPY(create_object)
COPY(get_iterator)
COPY(interface_gets_implemented)
#ifdef ZEND_ENGINE_2_3
# ifdef ZEND_ENGINE_2_3
COPY(get_static_method)
#endif
# endif
COPY(serialize)
COPY(unserialize)
/* deal with it inside xc_fix_method */
@ -387,20 +452,22 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
COPY(__get)
COPY(__set)
/* should be >5.1 */
#ifdef ZEND_ENGINE_2_1
# ifdef ZEND_ENGINE_2_1
COPY(__unset)
COPY(__isset)
# if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
# if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
COPY(__tostring)
# endif
#endif
# endif
# endif
COPY(__call)
#ifdef ZEND_CALLSTATIC_FUNC_NAME
# ifdef ZEND_CALLSTATIC_FUNC_NAME
COPY(__callstatic)
#endif
# endif
# ifndef ZEND_ENGINE_2_4
/* # NOT DONE */
COPY(module)
#else
# endif
#else /* ZEND_ENGINE_2 */
COPY(handle_function_call)
COPY(handle_property_get)
COPY(handle_property_set)
@ -414,6 +481,52 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
')
')
dnl }}}
#ifdef ZEND_ENGINE_2_4
undefine(`UNION_znode_op')
define(`UNION_znode_op', `dnl {{{
assert(src->$1_type == IS_CONST ||
src->$1_type == IS_VAR ||
src->$1_type == IS_CV ||
src->$1_type == IS_TMP_VAR ||
src->$1_type == IS_UNUSED);
dnl dirty dispatch
DISABLECHECK(`
switch (src->$1_type) {
case IS_CONST:
dnl TODO: fix me, use literals
IFDASM(`{
zval *zv;
ALLOC_INIT_ZVAL(zv);
*zv = ((zend_literal *) src->$1.ptr)->constant;
zval_copy_ctor(zv);
add_assoc_zval_ex(dst, ZEND_STRS("$1.constant"), zv);
}
', `
DISPATCH(zend_uint, $1.constant)
')
break;
IFCOPY(`
IFNOTMEMCPY(`
default:
*dst = *src;
')
', `
case IS_VAR:
case IS_TMP_VAR:
case IS_CV:
DISPATCH(zend_uint, $1.var)
break;
case IS_UNUSED:
IFDASM(`DISPATCH(zend_uint, $1.var)')
DISPATCH(zend_uint, $1.opline_num)
break;
')
}
')
DONE($1)
')
dnl }}}
#else
DEF_STRUCT_P_FUNC(`znode', , `dnl {{{
DISPATCH(int, op_type)
@ -458,24 +571,39 @@ DEF_STRUCT_P_FUNC(`znode', , `dnl {{{
}
')
DONE(u)
#if 0
DONE(EA)
#endif
#undef XCACHE_IS_CV
')
dnl }}}
#endif
DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
DISPATCH(zend_uchar, opcode)
#ifdef ZEND_ENGINE_2_4
UNION_znode_op(result)
UNION_znode_op(op1)
UNION_znode_op(op2)
#else
STRUCT(znode, result)
STRUCT(znode, op1)
STRUCT(znode, op2)
#endif
DISPATCH(ulong, extended_value)
DISPATCH(uint, lineno)
#ifdef ZEND_ENGINE_2_1
#ifdef ZEND_ENGINE_2_4
DISPATCH(zend_uchar, op1_type)
DISPATCH(zend_uchar, op2_type)
DISPATCH(zend_uchar, result_type)
#endif
IFCOPY(`
switch (src->opcode) {
#ifdef ZEND_GOTO
case ZEND_GOTO:
#endif
case ZEND_JMP:
dst->op1.u.jmp_addr = processor->active_opcodes_dst + (src->op1.u.jmp_addr - processor->active_opcodes_src);
Z_OP(dst->op1).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op1).jmp_addr - processor->active_opcodes_src);
break;
case ZEND_JMPZ:
@ -485,7 +613,7 @@ DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
#ifdef ZEND_JMP_SET
case ZEND_JMP_SET:
#endif
dst->op2.u.jmp_addr = processor->active_opcodes_dst + (src->op2.u.jmp_addr - processor->active_opcodes_src);
Z_OP(dst->op2).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op2).jmp_addr - processor->active_opcodes_src);
break;
default:
@ -496,6 +624,14 @@ DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
#endif
')
dnl }}}
#ifdef ZEND_ENGINE_2_4
DEF_STRUCT_P_FUNC(`zend_literal', , `dnl {{{
STRUCT(zval, constant)
DISPATCH(zend_ulong, hash_value)
DISPATCH(zend_uint, cache_slot)
')
dnl }}}
#endif
DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
IFRESTORE(`
dnl shadow copy must NOT meet:
@ -534,13 +670,14 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
DISPATCH(zend_uint, num_args)
DISPATCH(zend_uint, required_num_args)
# ifndef ZEND_ENGINE_2_4
DISPATCH(zend_bool, pass_rest_by_reference)
# endif
#else
if (src->arg_types) {
ALLOC(dst->arg_types, zend_uchar, src->arg_types[0] + 1)
IFCOPY(`memcpy(dst->arg_types, src->arg_types, sizeof(src->arg_types[0]) * (src->arg_types[0]+1));')
IFDASM(`do {
zend_uint ii;
int i;
zval *zv;
ALLOC_INIT_ZVAL(zv);
@ -566,7 +703,9 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
')
}
#endif
#ifndef ZEND_ENGINE_2_4
DISPATCH(unsigned char, return_reference)
#endif
/* END of common elements */
#ifdef IS_UNICODE
dnl SETNULL(u_twin)
@ -583,12 +722,16 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
STRUCT_ARRAY_I(last, zend_op, opcodes)
popdef(`AFTER_ALLOC')
DISPATCH(zend_uint, last)
#ifndef ZEND_ENGINE_2_4
IFCOPY(`dst->size = src->last;DONE(size)', `DISPATCH(zend_uint, size)')
#endif
#ifdef IS_CV
STRUCT_ARRAY(last_var, zend_compiled_variable, vars)
DISPATCH(int, last_var)
# ifndef ZEND_ENGINE_2_4
IFCOPY(`dst->size_var = src->last_var;DONE(size_var)', `DISPATCH(zend_uint, size_var)')
# endif
#else
dnl zend_cv.m4 is illegal to be made public, don not ask me for it
IFDASM(`
@ -600,7 +743,9 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
STRUCT_ARRAY_I(last_brk_cont, zend_brk_cont_element, brk_cont_array)
DISPATCH(zend_uint, last_brk_cont)
#ifndef ZEND_ENGINE_2_4
DISPATCH(zend_uint, current_brk_cont)
#endif
#ifndef ZEND_ENGINE_2
DISPATCH(zend_bool, uses_globals)
#endif
@ -612,13 +757,17 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
#ifndef ZEND_ENGINE_2_4
COPY(start_op)
DISPATCH(int, backpatch_count)
#endif
#ifdef ZEND_ENGINE_2_3
DISPATCH(zend_uint, this_var)
#endif
#ifndef ZEND_ENGINE_2_4
DISPATCH(zend_bool, done_pass_two)
#endif
/* 5.0 <= ver < 5.3 */
#if defined(ZEND_ENGINE_2) && !defined(ZEND_ENGINE_2_3)
DISPATCH(zend_bool, uses_this)
@ -646,6 +795,13 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
DONE(reserved)
#if defined(HARDENING_PATCH) && HARDENING_PATCH
DISPATCH(zend_bool, created_by_eval)
#endif
#ifdef ZEND_ENGINE_2_4
DISPATCH(int, last_literal)
IFRESTORE(`COPY(literals)', `STRUCT_ARRAY_I(last_literal, zend_literal, literals)')
COPYNULL(run_time_cache)
COPYNULL(last_cache_slot)
#endif
} while (0);
@ -679,6 +835,7 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
COPYNULL(prototype)
')
')
#endif
#ifdef ZEND_ENGINE_2

25
processor/struct.m4

@ -29,11 +29,10 @@ define(`DEF_STRUCT_P_FUNC', `
DECL_STRUCT_P_FUNC(`$1', `$2', 1)
{
pushdef(`ELEMENTS_DONE')
ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')define(`SIZEOF_$1', 0)')
IFASSERT(`
/* {{{ init assert */
ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')define(`SIZEOF_$1', 0)')
ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore')define(`COUNTOF_$1', 0)')
ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')')
ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore'))')
dnl SIZEOF_x COUNTOF_x can be both defined or both not
ifdef(`SIZEOF_$1', `
ifdef(`COUNTOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing COUNTOF_$1')')
@ -47,11 +46,15 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1)
')
int assert_size = SIZEOF_$1, assert_count = COUNTOF_$1;
int done_size = 0, done_count = 0;
const char *assert_names[] = { ifdef(`ELEMENTSOF_$1', `ELEMENTSOF_$1') };
HashTable done_names;
zend_hash_init(&done_names, 0, NULL, NULL, 0);
/* }}} */
IFRESTORE(`assert(xc_is_shm(src));')
IFCALCSTORE(`assert(!xc_is_shm(src));')
do {
')
ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')')
ifdef(`USEMEMCPY', `IFCOPY(`
memcpy(dst, src, sizeof($1));
@ -67,9 +70,17 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1)
indent --;
INDENT()fprintf(stderr, "}\n");
')
ifdef(`SKIPASSERT_ONCE', `undefine(`SKIPASSERT_ONCE')', `
ifdef(`SKIPASSERT_ONCE', `
undefine(`SKIPASSERT_ONCE')
IFASSERT(`
/* {{{ check assert */