phpdbg_opcode.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Felipe Pena <felipe@php.net> |
  16. | Authors: Joe Watkins <joe.watkins@live.co.uk> |
  17. | Authors: Bob Weinand <bwoebi@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #include "phpdbg.h"
  21. #include "zend_vm_opcodes.h"
  22. #include "zend_compile.h"
  23. #include "phpdbg_opcode.h"
  24. #include "phpdbg_utils.h"
  25. ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
  26. static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */
  27. {
  28. int iter = 0;
  29. while (iter < ops->last_literal) {
  30. if (literal == &ops->literals[iter]) {
  31. return iter;
  32. }
  33. iter++;
  34. }
  35. return 0;
  36. } /* }}} */
  37. static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */
  38. {
  39. char *decode = NULL;
  40. switch (type &~ EXT_TYPE_UNUSED) {
  41. case IS_CV:
  42. asprintf(&decode, "$%s", ops->vars[op->var].name);
  43. break;
  44. case IS_VAR:
  45. case IS_TMP_VAR: {
  46. zend_ulong id = 0, *pid = NULL;
  47. if (vars != NULL) {
  48. if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) {
  49. id = zend_hash_num_elements(vars);
  50. zend_hash_index_update(
  51. vars, (zend_ulong) ops->vars - op->var,
  52. (void**) &id,
  53. sizeof(zend_ulong), NULL);
  54. } else id = *pid;
  55. }
  56. asprintf(&decode, "@%lu", id);
  57. } break;
  58. case IS_CONST:
  59. asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->literal TSRMLS_CC));
  60. break;
  61. case IS_UNUSED:
  62. asprintf(&decode, "<unused>");
  63. break;
  64. }
  65. return decode;
  66. } /* }}} */
  67. char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */
  68. {
  69. char *decode[4] = {NULL, NULL, NULL, NULL};
  70. switch (op->opcode) {
  71. case ZEND_JMP:
  72. #ifdef ZEND_GOTO
  73. case ZEND_GOTO:
  74. #endif
  75. #ifdef ZEND_FAST_CALL
  76. case ZEND_FAST_CALL:
  77. #endif
  78. asprintf(&decode[1], "J%ld", op->op1.jmp_addr - ops->opcodes);
  79. goto format;
  80. case ZEND_JMPZNZ:
  81. decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC);
  82. asprintf(
  83. &decode[2], "J%u or J%lu", op->op2.opline_num, op->extended_value);
  84. goto result;
  85. case ZEND_JMPZ:
  86. case ZEND_JMPNZ:
  87. case ZEND_JMPZ_EX:
  88. case ZEND_JMPNZ_EX:
  89. #ifdef ZEND_JMP_SET
  90. case ZEND_JMP_SET:
  91. #endif
  92. #ifdef ZEND_JMP_SET_VAR
  93. case ZEND_JMP_SET_VAR:
  94. #endif
  95. decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC);
  96. asprintf(
  97. &decode[2], "J%ld", op->op2.jmp_addr - ops->opcodes);
  98. goto result;
  99. case ZEND_RECV_INIT:
  100. goto result;
  101. default: {
  102. decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC);
  103. decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC);
  104. result:
  105. decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC);
  106. format:
  107. asprintf(
  108. &decode[0],
  109. "%-20s %-20s %-20s",
  110. decode[1] ? decode[1] : "",
  111. decode[2] ? decode[2] : "",
  112. decode[3] ? decode[3] : "");
  113. }
  114. }
  115. if (decode[1])
  116. free(decode[1]);
  117. if (decode[2])
  118. free(decode[2]);
  119. if (decode[3])
  120. free(decode[3]);
  121. return decode[0];
  122. } /* }}} */
  123. void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC) /* {{{ */
  124. {
  125. /* force out a line while stepping so the user knows what is happening */
  126. if (ignore_flags ||
  127. (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) ||
  128. (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ||
  129. (PHPDBG_G(oplog)))) {
  130. zend_op *opline = execute_data->opline;
  131. char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC);
  132. if (ignore_flags || (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) {
  133. /* output line info */
  134. phpdbg_notice("L%-5u %16p %-30s %s %s",
  135. opline->lineno,
  136. opline,
  137. phpdbg_decode_opcode(opline->opcode),
  138. decode,
  139. execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
  140. }
  141. if (!ignore_flags && PHPDBG_G(oplog)) {
  142. phpdbg_log_ex(PHPDBG_G(oplog), "L%-5u %16p %-30s %s %s",
  143. opline->lineno,
  144. opline,
  145. phpdbg_decode_opcode(opline->opcode),
  146. decode,
  147. execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
  148. }
  149. if (decode) {
  150. free(decode);
  151. }
  152. }
  153. } /* }}} */
  154. void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC) /* {{{ */
  155. {
  156. phpdbg_print_opline_ex(execute_data, NULL, ignore_flags TSRMLS_CC);
  157. } /* }}} */
  158. const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */
  159. {
  160. #if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
  161. #define CASE(s) case s: return #s
  162. switch (opcode) {
  163. CASE(ZEND_NOP);
  164. CASE(ZEND_ADD);
  165. CASE(ZEND_SUB);
  166. CASE(ZEND_MUL);
  167. CASE(ZEND_DIV);
  168. CASE(ZEND_MOD);
  169. CASE(ZEND_SL);
  170. CASE(ZEND_SR);
  171. CASE(ZEND_CONCAT);
  172. CASE(ZEND_BW_OR);
  173. CASE(ZEND_BW_AND);
  174. CASE(ZEND_BW_XOR);
  175. CASE(ZEND_BW_NOT);
  176. CASE(ZEND_BOOL_NOT);
  177. CASE(ZEND_BOOL_XOR);
  178. CASE(ZEND_IS_IDENTICAL);
  179. CASE(ZEND_IS_NOT_IDENTICAL);
  180. CASE(ZEND_IS_EQUAL);
  181. CASE(ZEND_IS_NOT_EQUAL);
  182. CASE(ZEND_IS_SMALLER);
  183. CASE(ZEND_IS_SMALLER_OR_EQUAL);
  184. CASE(ZEND_CAST);
  185. CASE(ZEND_QM_ASSIGN);
  186. CASE(ZEND_ASSIGN_ADD);
  187. CASE(ZEND_ASSIGN_SUB);
  188. CASE(ZEND_ASSIGN_MUL);
  189. CASE(ZEND_ASSIGN_DIV);
  190. CASE(ZEND_ASSIGN_MOD);
  191. CASE(ZEND_ASSIGN_SL);
  192. CASE(ZEND_ASSIGN_SR);
  193. CASE(ZEND_ASSIGN_CONCAT);
  194. CASE(ZEND_ASSIGN_BW_OR);
  195. CASE(ZEND_ASSIGN_BW_AND);
  196. CASE(ZEND_ASSIGN_BW_XOR);
  197. CASE(ZEND_PRE_INC);
  198. CASE(ZEND_PRE_DEC);
  199. CASE(ZEND_POST_INC);
  200. CASE(ZEND_POST_DEC);
  201. CASE(ZEND_ASSIGN);
  202. CASE(ZEND_ASSIGN_REF);
  203. CASE(ZEND_ECHO);
  204. CASE(ZEND_PRINT);
  205. CASE(ZEND_JMP);
  206. CASE(ZEND_JMPZ);
  207. CASE(ZEND_JMPNZ);
  208. CASE(ZEND_JMPZNZ);
  209. CASE(ZEND_JMPZ_EX);
  210. CASE(ZEND_JMPNZ_EX);
  211. CASE(ZEND_CASE);
  212. CASE(ZEND_SWITCH_FREE);
  213. CASE(ZEND_BRK);
  214. CASE(ZEND_CONT);
  215. CASE(ZEND_BOOL);
  216. CASE(ZEND_INIT_STRING);
  217. CASE(ZEND_ADD_CHAR);
  218. CASE(ZEND_ADD_STRING);
  219. CASE(ZEND_ADD_VAR);
  220. CASE(ZEND_BEGIN_SILENCE);
  221. CASE(ZEND_END_SILENCE);
  222. CASE(ZEND_INIT_FCALL_BY_NAME);
  223. CASE(ZEND_DO_FCALL);
  224. CASE(ZEND_DO_FCALL_BY_NAME);
  225. CASE(ZEND_RETURN);
  226. CASE(ZEND_RECV);
  227. CASE(ZEND_RECV_INIT);
  228. CASE(ZEND_SEND_VAL);
  229. CASE(ZEND_SEND_VAR);
  230. CASE(ZEND_SEND_REF);
  231. CASE(ZEND_NEW);
  232. CASE(ZEND_INIT_NS_FCALL_BY_NAME);
  233. CASE(ZEND_FREE);
  234. CASE(ZEND_INIT_ARRAY);
  235. CASE(ZEND_ADD_ARRAY_ELEMENT);
  236. CASE(ZEND_INCLUDE_OR_EVAL);
  237. CASE(ZEND_UNSET_VAR);
  238. CASE(ZEND_UNSET_DIM);
  239. CASE(ZEND_UNSET_OBJ);
  240. CASE(ZEND_FE_RESET);
  241. CASE(ZEND_FE_FETCH);
  242. CASE(ZEND_EXIT);
  243. CASE(ZEND_FETCH_R);
  244. CASE(ZEND_FETCH_DIM_R);
  245. CASE(ZEND_FETCH_OBJ_R);
  246. CASE(ZEND_FETCH_W);
  247. CASE(ZEND_FETCH_DIM_W);
  248. CASE(ZEND_FETCH_OBJ_W);
  249. CASE(ZEND_FETCH_RW);
  250. CASE(ZEND_FETCH_DIM_RW);
  251. CASE(ZEND_FETCH_OBJ_RW);
  252. CASE(ZEND_FETCH_IS);
  253. CASE(ZEND_FETCH_DIM_IS);
  254. CASE(ZEND_FETCH_OBJ_IS);
  255. CASE(ZEND_FETCH_FUNC_ARG);
  256. CASE(ZEND_FETCH_DIM_FUNC_ARG);
  257. CASE(ZEND_FETCH_OBJ_FUNC_ARG);
  258. CASE(ZEND_FETCH_UNSET);
  259. CASE(ZEND_FETCH_DIM_UNSET);
  260. CASE(ZEND_FETCH_OBJ_UNSET);
  261. CASE(ZEND_FETCH_DIM_TMP_VAR);
  262. CASE(ZEND_FETCH_CONSTANT);
  263. CASE(ZEND_GOTO);
  264. CASE(ZEND_EXT_STMT);
  265. CASE(ZEND_EXT_FCALL_BEGIN);
  266. CASE(ZEND_EXT_FCALL_END);
  267. CASE(ZEND_EXT_NOP);
  268. CASE(ZEND_TICKS);
  269. CASE(ZEND_SEND_VAR_NO_REF);
  270. CASE(ZEND_CATCH);
  271. CASE(ZEND_THROW);
  272. CASE(ZEND_FETCH_CLASS);
  273. CASE(ZEND_CLONE);
  274. CASE(ZEND_RETURN_BY_REF);
  275. CASE(ZEND_INIT_METHOD_CALL);
  276. CASE(ZEND_INIT_STATIC_METHOD_CALL);
  277. CASE(ZEND_ISSET_ISEMPTY_VAR);
  278. CASE(ZEND_ISSET_ISEMPTY_DIM_OBJ);
  279. CASE(ZEND_PRE_INC_OBJ);
  280. CASE(ZEND_PRE_DEC_OBJ);
  281. CASE(ZEND_POST_INC_OBJ);
  282. CASE(ZEND_POST_DEC_OBJ);
  283. CASE(ZEND_ASSIGN_OBJ);
  284. CASE(ZEND_INSTANCEOF);
  285. CASE(ZEND_DECLARE_CLASS);
  286. CASE(ZEND_DECLARE_INHERITED_CLASS);
  287. CASE(ZEND_DECLARE_FUNCTION);
  288. CASE(ZEND_RAISE_ABSTRACT_ERROR);
  289. CASE(ZEND_DECLARE_CONST);
  290. CASE(ZEND_ADD_INTERFACE);
  291. CASE(ZEND_DECLARE_INHERITED_CLASS_DELAYED);
  292. CASE(ZEND_VERIFY_ABSTRACT_CLASS);
  293. CASE(ZEND_ASSIGN_DIM);
  294. CASE(ZEND_ISSET_ISEMPTY_PROP_OBJ);
  295. CASE(ZEND_HANDLE_EXCEPTION);
  296. CASE(ZEND_USER_OPCODE);
  297. #ifdef ZEND_JMP_SET
  298. CASE(ZEND_JMP_SET);
  299. #endif
  300. CASE(ZEND_DECLARE_LAMBDA_FUNCTION);
  301. #ifdef ZEND_ADD_TRAIT
  302. CASE(ZEND_ADD_TRAIT);
  303. #endif
  304. #ifdef ZEND_BIND_TRAITS
  305. CASE(ZEND_BIND_TRAITS);
  306. #endif
  307. #ifdef ZEND_SEPARATE
  308. CASE(ZEND_SEPARATE);
  309. #endif
  310. #ifdef ZEND_QM_ASSIGN_VAR
  311. CASE(ZEND_QM_ASSIGN_VAR);
  312. #endif
  313. #ifdef ZEND_JMP_SET_VAR
  314. CASE(ZEND_JMP_SET_VAR);
  315. #endif
  316. #ifdef ZEND_DISCARD_EXCEPTION
  317. CASE(ZEND_DISCARD_EXCEPTION);
  318. #endif
  319. #ifdef ZEND_YIELD
  320. CASE(ZEND_YIELD);
  321. #endif
  322. #ifdef ZEND_GENERATOR_RETURN
  323. CASE(ZEND_GENERATOR_RETURN);
  324. #endif
  325. #ifdef ZEND_FAST_CALL
  326. CASE(ZEND_FAST_CALL);
  327. #endif
  328. #ifdef ZEND_FAST_RET
  329. CASE(ZEND_FAST_RET);
  330. #endif
  331. #ifdef ZEND_RECV_VARIADIC
  332. CASE(ZEND_RECV_VARIADIC);
  333. #endif
  334. CASE(ZEND_OP_DATA);
  335. default:
  336. return "UNKNOWN";
  337. }
  338. #else
  339. const char *ret = zend_get_opcode_name(opcode);
  340. return ret?ret:"UNKNOWN";
  341. #endif
  342. } /* }}} */