zend_dump.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine, Bytecode Visualisation |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 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: Dmitry Stogov <dmitry@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "zend_compile.h"
  20. #include "zend_cfg.h"
  21. #include "zend_ssa.h"
  22. #include "zend_inference.h"
  23. #include "zend_func_info.h"
  24. #include "zend_call_graph.h"
  25. #include "zend_dump.h"
  26. void zend_dump_ht(HashTable *ht)
  27. {
  28. zend_ulong index;
  29. zend_string *key;
  30. zval *val;
  31. int first = 1;
  32. ZEND_HASH_FOREACH_KEY_VAL(ht, index, key, val) {
  33. if (first) {
  34. first = 0;
  35. } else {
  36. fprintf(stderr, ", ");
  37. }
  38. if (key) {
  39. fprintf(stderr, "\"%s\"", ZSTR_VAL(key));
  40. } else {
  41. fprintf(stderr, ZEND_LONG_FMT, index);
  42. }
  43. fprintf(stderr, " =>");
  44. zend_dump_const(val);
  45. } ZEND_HASH_FOREACH_END();
  46. }
  47. void zend_dump_const(const zval *zv)
  48. {
  49. switch (Z_TYPE_P(zv)) {
  50. case IS_NULL:
  51. fprintf(stderr, " null");
  52. break;
  53. case IS_FALSE:
  54. fprintf(stderr, " bool(false)");
  55. break;
  56. case IS_TRUE:
  57. fprintf(stderr, " bool(true)");
  58. break;
  59. case IS_LONG:
  60. fprintf(stderr, " int(" ZEND_LONG_FMT ")", Z_LVAL_P(zv));
  61. break;
  62. case IS_DOUBLE:
  63. fprintf(stderr, " float(%g)", Z_DVAL_P(zv));
  64. break;
  65. case IS_STRING:
  66. fprintf(stderr, " string(\"%s\")", Z_STRVAL_P(zv));
  67. break;
  68. case IS_ARRAY:
  69. fprintf(stderr, " array(...)");
  70. break;
  71. default:
  72. fprintf(stderr, " zval(type=%d)", Z_TYPE_P(zv));
  73. break;
  74. }
  75. }
  76. static void zend_dump_class_fetch_type(uint32_t fetch_type)
  77. {
  78. switch (fetch_type & ZEND_FETCH_CLASS_MASK) {
  79. case ZEND_FETCH_CLASS_SELF:
  80. fprintf(stderr, " (self)");
  81. break;
  82. case ZEND_FETCH_CLASS_PARENT:
  83. fprintf(stderr, " (parent)");
  84. break;
  85. case ZEND_FETCH_CLASS_STATIC:
  86. fprintf(stderr, " (static)");
  87. break;
  88. case ZEND_FETCH_CLASS_AUTO:
  89. fprintf(stderr, " (auto)");
  90. break;
  91. case ZEND_FETCH_CLASS_INTERFACE:
  92. fprintf(stderr, " (interface)");
  93. break;
  94. case ZEND_FETCH_CLASS_TRAIT:
  95. fprintf(stderr, " (trait)");
  96. break;
  97. }
  98. if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
  99. fprintf(stderr, " (no-autolod)");
  100. }
  101. if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
  102. fprintf(stderr, " (silent)");
  103. }
  104. if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
  105. fprintf(stderr, " (exception)");
  106. }
  107. }
  108. static void zend_dump_unused_op(const zend_op *opline, znode_op op, uint32_t flags) {
  109. if (ZEND_VM_OP_NUM == (flags & ZEND_VM_OP_MASK)) {
  110. fprintf(stderr, " %u", op.num);
  111. } else if (ZEND_VM_OP_TRY_CATCH == (flags & ZEND_VM_OP_MASK)) {
  112. if (op.num != (uint32_t)-1) {
  113. fprintf(stderr, " try-catch(%u)", op.num);
  114. }
  115. } else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) {
  116. fprintf(stderr, " THIS");
  117. } else if (ZEND_VM_OP_NEXT == (flags & ZEND_VM_OP_MASK)) {
  118. fprintf(stderr, " NEXT");
  119. } else if (ZEND_VM_OP_CLASS_FETCH == (flags & ZEND_VM_OP_MASK)) {
  120. zend_dump_class_fetch_type(op.num);
  121. } else if (ZEND_VM_OP_CONSTRUCTOR == (flags & ZEND_VM_OP_MASK)) {
  122. fprintf(stderr, " CONSTRUCTOR");
  123. } else if (ZEND_VM_OP_CONST_FETCH == (flags & ZEND_VM_OP_MASK)) {
  124. if (op.num & IS_CONSTANT_UNQUALIFIED) {
  125. fprintf(stderr, " (unqualified)");
  126. }
  127. if (op.num & IS_CONSTANT_IN_NAMESPACE) {
  128. fprintf(stderr, " (in-namespace)");
  129. }
  130. }
  131. }
  132. void zend_dump_var(const zend_op_array *op_array, zend_uchar var_type, int var_num)
  133. {
  134. if (var_type == IS_CV && var_num < op_array->last_var) {
  135. fprintf(stderr, "CV%d($%s)", var_num, op_array->vars[var_num]->val);
  136. } else if (var_type == IS_VAR) {
  137. fprintf(stderr, "V%d", var_num);
  138. } else if (var_type == IS_TMP_VAR) {
  139. fprintf(stderr, "T%d", var_num);
  140. } else {
  141. fprintf(stderr, "X%d", var_num);
  142. }
  143. }
  144. static void zend_dump_range(const zend_ssa_range *r)
  145. {
  146. if (r->underflow && r->overflow) {
  147. return;
  148. }
  149. fprintf(stderr, " RANGE[");
  150. if (r->underflow) {
  151. fprintf(stderr, "--..");
  152. } else {
  153. fprintf(stderr, ZEND_LONG_FMT "..", r->min);
  154. }
  155. if (r->overflow) {
  156. fprintf(stderr, "++]");
  157. } else {
  158. fprintf(stderr, ZEND_LONG_FMT "]", r->max);
  159. }
  160. }
  161. static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_instanceof, uint32_t dump_flags)
  162. {
  163. int first = 1;
  164. fprintf(stderr, " [");
  165. if (info & MAY_BE_UNDEF) {
  166. if (first) first = 0; else fprintf(stderr, ", ");
  167. fprintf(stderr, "undef");
  168. }
  169. if (info & MAY_BE_REF) {
  170. if (first) first = 0; else fprintf(stderr, ", ");
  171. fprintf(stderr, "ref");
  172. }
  173. if (dump_flags & ZEND_DUMP_RC_INFERENCE) {
  174. if (info & MAY_BE_RC1) {
  175. if (first) first = 0; else fprintf(stderr, ", ");
  176. fprintf(stderr, "rc1");
  177. }
  178. if (info & MAY_BE_RCN) {
  179. if (first) first = 0; else fprintf(stderr, ", ");
  180. fprintf(stderr, "rcn");
  181. }
  182. }
  183. if (info & MAY_BE_CLASS) {
  184. if (first) first = 0; else fprintf(stderr, ", ");
  185. fprintf(stderr, "class");
  186. if (ce) {
  187. if (is_instanceof) {
  188. fprintf(stderr, " (instanceof %s)", ce->name->val);
  189. } else {
  190. fprintf(stderr, " (%s)", ce->name->val);
  191. }
  192. }
  193. } else if ((info & MAY_BE_ANY) == MAY_BE_ANY) {
  194. if (first) first = 0; else fprintf(stderr, ", ");
  195. fprintf(stderr, "any");
  196. } else {
  197. if (info & MAY_BE_NULL) {
  198. if (first) first = 0; else fprintf(stderr, ", ");
  199. fprintf(stderr, "null");
  200. }
  201. if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) {
  202. if (first) first = 0; else fprintf(stderr, ", ");
  203. fprintf(stderr, "bool");
  204. } else if (info & MAY_BE_FALSE) {
  205. if (first) first = 0; else fprintf(stderr, ", ");
  206. fprintf(stderr, "false");
  207. } else if (info & MAY_BE_TRUE) {
  208. if (first) first = 0; else fprintf(stderr, ", ");
  209. fprintf(stderr, "true");
  210. }
  211. if (info & MAY_BE_LONG) {
  212. if (first) first = 0; else fprintf(stderr, ", ");
  213. fprintf(stderr, "long");
  214. }
  215. if (info & MAY_BE_DOUBLE) {
  216. if (first) first = 0; else fprintf(stderr, ", ");
  217. fprintf(stderr, "double");
  218. }
  219. if (info & MAY_BE_STRING) {
  220. if (first) first = 0; else fprintf(stderr, ", ");
  221. fprintf(stderr, "string");
  222. }
  223. if (info & MAY_BE_ARRAY) {
  224. if (first) first = 0; else fprintf(stderr, ", ");
  225. fprintf(stderr, "array");
  226. if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 &&
  227. (info & MAY_BE_ARRAY_KEY_ANY) != MAY_BE_ARRAY_KEY_ANY) {
  228. int afirst = 1;
  229. fprintf(stderr, " [");
  230. if (info & MAY_BE_ARRAY_KEY_LONG) {
  231. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  232. fprintf(stderr, "long");
  233. }
  234. if (info & MAY_BE_ARRAY_KEY_STRING) {
  235. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  236. fprintf(stderr, "string");
  237. }
  238. fprintf(stderr, "]");
  239. }
  240. if (info & (MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF)) {
  241. int afirst = 1;
  242. fprintf(stderr, " of [");
  243. if ((info & MAY_BE_ARRAY_OF_ANY) == MAY_BE_ARRAY_OF_ANY) {
  244. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  245. fprintf(stderr, "any");
  246. } else {
  247. if (info & MAY_BE_ARRAY_OF_NULL) {
  248. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  249. fprintf(stderr, "null");
  250. }
  251. if (info & MAY_BE_ARRAY_OF_FALSE) {
  252. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  253. fprintf(stderr, "false");
  254. }
  255. if (info & MAY_BE_ARRAY_OF_TRUE) {
  256. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  257. fprintf(stderr, "true");
  258. }
  259. if (info & MAY_BE_ARRAY_OF_LONG) {
  260. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  261. fprintf(stderr, "long");
  262. }
  263. if (info & MAY_BE_ARRAY_OF_DOUBLE) {
  264. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  265. fprintf(stderr, "double");
  266. }
  267. if (info & MAY_BE_ARRAY_OF_STRING) {
  268. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  269. fprintf(stderr, "string");
  270. }
  271. if (info & MAY_BE_ARRAY_OF_ARRAY) {
  272. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  273. fprintf(stderr, "array");
  274. }
  275. if (info & MAY_BE_ARRAY_OF_OBJECT) {
  276. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  277. fprintf(stderr, "object");
  278. }
  279. if (info & MAY_BE_ARRAY_OF_RESOURCE) {
  280. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  281. fprintf(stderr, "resource");
  282. }
  283. }
  284. if (info & MAY_BE_ARRAY_OF_REF) {
  285. if (afirst) afirst = 0; else fprintf(stderr, ", ");
  286. fprintf(stderr, "ref");
  287. }
  288. fprintf(stderr, "]");
  289. }
  290. }
  291. if (info & MAY_BE_OBJECT) {
  292. if (first) first = 0; else fprintf(stderr, ", ");
  293. fprintf(stderr, "object");
  294. if (ce) {
  295. if (is_instanceof) {
  296. fprintf(stderr, " (instanceof %s)", ce->name->val);
  297. } else {
  298. fprintf(stderr, " (%s)", ce->name->val);
  299. }
  300. }
  301. }
  302. if (info & MAY_BE_RESOURCE) {
  303. if (first) first = 0; else fprintf(stderr, ", ");
  304. fprintf(stderr, "resource");
  305. }
  306. }
  307. if (info & MAY_BE_ERROR) {
  308. if (first) first = 0; else fprintf(stderr, ", ");
  309. fprintf(stderr, "error");
  310. }
  311. //TODO: this is useful only for JIT???
  312. if (info & MAY_BE_IN_REG) {
  313. if (first) first = 0; else fprintf(stderr, ", ");
  314. fprintf(stderr, "reg");
  315. }
  316. fprintf(stderr, "]");
  317. }
  318. static void zend_dump_ssa_var_info(const zend_ssa *ssa, int ssa_var_num, uint32_t dump_flags)
  319. {
  320. zend_dump_type_info(
  321. ssa->var_info[ssa_var_num].type,
  322. ssa->var_info[ssa_var_num].ce,
  323. ssa->var_info[ssa_var_num].ce ?
  324. ssa->var_info[ssa_var_num].is_instanceof : 0,
  325. dump_flags);
  326. }
  327. 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)
  328. {
  329. if (ssa_var_num >= 0) {
  330. fprintf(stderr, "#%d.", ssa_var_num);
  331. } else {
  332. fprintf(stderr, "#?.");
  333. }
  334. zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : var_type), var_num);
  335. if (ssa_var_num >= 0 && ssa->vars) {
  336. if (ssa->vars[ssa_var_num].no_val) {
  337. fprintf(stderr, " NOVAL");
  338. }
  339. if (ssa->vars[ssa_var_num].escape_state == ESCAPE_STATE_NO_ESCAPE) {
  340. fprintf(stderr, " NOESC");
  341. }
  342. if (ssa->var_info) {
  343. zend_dump_ssa_var_info(ssa, ssa_var_num, dump_flags);
  344. if (ssa->var_info[ssa_var_num].has_range) {
  345. zend_dump_range(&ssa->var_info[ssa_var_num].range);
  346. }
  347. }
  348. }
  349. }
  350. static void zend_dump_type_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_type_constraint *constraint, uint32_t dump_flags)
  351. {
  352. fprintf(stderr, " TYPE");
  353. zend_dump_type_info(constraint->type_mask, constraint->ce, 1, dump_flags);
  354. }
  355. static void zend_dump_range_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_range_constraint *r, uint32_t dump_flags)
  356. {
  357. if (r->range.underflow && r->range.overflow) {
  358. return;
  359. }
  360. fprintf(stderr, " RANGE");
  361. if (r->negative) {
  362. fprintf(stderr, "~");
  363. }
  364. fprintf(stderr, "[");
  365. if (r->range.underflow) {
  366. fprintf(stderr, "-- .. ");
  367. } else {
  368. if (r->min_ssa_var >= 0) {
  369. zend_dump_ssa_var(op_array, ssa, r->min_ssa_var, (r->min_var < op_array->last_var ? IS_CV : 0), r->min_var, dump_flags);
  370. if (r->range.min > 0) {
  371. fprintf(stderr, " + " ZEND_LONG_FMT, r->range.min);
  372. } else if (r->range.min < 0) {
  373. fprintf(stderr, " - " ZEND_LONG_FMT, -r->range.min);
  374. }
  375. fprintf(stderr, " .. ");
  376. } else {
  377. fprintf(stderr, ZEND_LONG_FMT " .. ", r->range.min);
  378. }
  379. }
  380. if (r->range.overflow) {
  381. fprintf(stderr, "++]");
  382. } else {
  383. if (r->max_ssa_var >= 0) {
  384. zend_dump_ssa_var(op_array, ssa, r->max_ssa_var, (r->max_var < op_array->last_var ? IS_CV : 0), r->max_var, dump_flags);
  385. if (r->range.max > 0) {
  386. fprintf(stderr, " + " ZEND_LONG_FMT, r->range.max);
  387. } else if (r->range.max < 0) {
  388. fprintf(stderr, " - " ZEND_LONG_FMT, -r->range.max);
  389. }
  390. fprintf(stderr, "]");
  391. } else {
  392. fprintf(stderr, ZEND_LONG_FMT "]", r->range.max);
  393. }
  394. }
  395. }
  396. 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)
  397. {
  398. const char *name = zend_get_opcode_name(opline->opcode);
  399. uint32_t flags = zend_get_opcode_flags(opline->opcode);
  400. uint32_t n = 0;
  401. int len = 0;
  402. const zend_ssa *ssa = NULL;
  403. if (dump_flags & ZEND_DUMP_SSA) {
  404. ssa = (const zend_ssa*)data;
  405. }
  406. if (!b) {
  407. len = fprintf(stderr, "L%u (%u):", (uint32_t)(opline - op_array->opcodes), opline->lineno);
  408. }
  409. fprintf(stderr, "%*c", 12-len, ' ');
  410. if (!ssa || !ssa->ops || ssa->ops[opline - op_array->opcodes].result_use < 0) {
  411. if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  412. if (ssa && ssa->ops && ssa->ops[opline - op_array->opcodes].result_def >= 0) {
  413. int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def;
  414. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
  415. } else {
  416. zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var));
  417. }
  418. fprintf(stderr, " = ");
  419. }
  420. }
  421. if (name) {
  422. fprintf(stderr, "%s", (name + 5));
  423. } else {
  424. fprintf(stderr, "OP_%d", (int)opline->opcode);
  425. }
  426. if (ZEND_VM_EXT_NUM == (flags & ZEND_VM_EXT_MASK)) {
  427. fprintf(stderr, " %u", opline->extended_value);
  428. } else if (ZEND_VM_EXT_DIM_OBJ == (flags & ZEND_VM_EXT_MASK)) {
  429. if (opline->extended_value == ZEND_ASSIGN_DIM) {
  430. fprintf(stderr, " (dim)");
  431. } else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
  432. fprintf(stderr, " (obj)");
  433. }
  434. } else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) {
  435. switch (opline->extended_value) {
  436. case IS_NULL:
  437. fprintf(stderr, " (null)");
  438. break;
  439. case IS_FALSE:
  440. fprintf(stderr, " (false)");
  441. break;
  442. case IS_TRUE:
  443. fprintf(stderr, " (true)");
  444. break;
  445. case IS_LONG:
  446. fprintf(stderr, " (long)");
  447. break;
  448. case IS_DOUBLE:
  449. fprintf(stderr, " (double)");
  450. break;
  451. case IS_STRING:
  452. fprintf(stderr, " (string)");
  453. break;
  454. case IS_ARRAY:
  455. fprintf(stderr, " (array)");
  456. break;
  457. case IS_OBJECT:
  458. fprintf(stderr, " (object)");
  459. break;
  460. case IS_RESOURCE:
  461. fprintf(stderr, " (resource)");
  462. break;
  463. case _IS_BOOL:
  464. fprintf(stderr, " (bool)");
  465. break;
  466. case IS_CALLABLE:
  467. fprintf(stderr, " (callable)");
  468. break;
  469. case IS_VOID:
  470. fprintf(stderr, " (void)");
  471. break;
  472. default:
  473. fprintf(stderr, " (\?\?\?)");
  474. break;
  475. }
  476. } else if (ZEND_VM_EXT_TYPE_MASK == (flags & ZEND_VM_EXT_MASK)) {
  477. switch (opline->extended_value) {
  478. case (1<<IS_NULL):
  479. fprintf(stderr, " (null)");
  480. break;
  481. case (1<<IS_FALSE):
  482. fprintf(stderr, " (false)");
  483. break;
  484. case (1<<IS_TRUE):
  485. fprintf(stderr, " (true)");
  486. break;
  487. case (1<<IS_LONG):
  488. fprintf(stderr, " (long)");
  489. break;
  490. case (1<<IS_DOUBLE):
  491. fprintf(stderr, " (double)");
  492. break;
  493. case (1<<IS_STRING):
  494. fprintf(stderr, " (string)");
  495. break;
  496. case (1<<IS_ARRAY):
  497. fprintf(stderr, " (array)");
  498. break;
  499. case (1<<IS_OBJECT):
  500. fprintf(stderr, " (object)");
  501. break;
  502. case (1<<IS_RESOURCE):
  503. fprintf(stderr, " (resource)");
  504. break;
  505. case ((1<<IS_FALSE)|(1<<IS_TRUE)):
  506. fprintf(stderr, " (bool)");
  507. break;
  508. default:
  509. fprintf(stderr, " (\?\?\?)");
  510. break;
  511. }
  512. } else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) {
  513. switch (opline->extended_value) {
  514. case ZEND_EVAL:
  515. fprintf(stderr, " (eval)");
  516. break;
  517. case ZEND_INCLUDE:
  518. fprintf(stderr, " (include)");
  519. break;
  520. case ZEND_INCLUDE_ONCE:
  521. fprintf(stderr, " (include_once)");
  522. break;
  523. case ZEND_REQUIRE:
  524. fprintf(stderr, " (require)");
  525. break;
  526. case ZEND_REQUIRE_ONCE:
  527. fprintf(stderr, " (require_once)");
  528. break;
  529. default:
  530. fprintf(stderr, " (\?\?\?)");
  531. break;
  532. }
  533. } else if (ZEND_VM_EXT_SRC == (flags & ZEND_VM_EXT_MASK)) {
  534. if (opline->extended_value == ZEND_RETURNS_VALUE) {
  535. fprintf(stderr, " (value)");
  536. } else if (opline->extended_value == ZEND_RETURNS_FUNCTION) {
  537. fprintf(stderr, " (function)");
  538. }
  539. } else {
  540. if (ZEND_VM_EXT_VAR_FETCH & flags) {
  541. if (opline->extended_value & ZEND_FETCH_GLOBAL) {
  542. fprintf(stderr, " (global)");
  543. } else if (opline->extended_value & ZEND_FETCH_LOCAL) {
  544. fprintf(stderr, " (local)");
  545. } else if (opline->extended_value & ZEND_FETCH_GLOBAL_LOCK) {
  546. fprintf(stderr, " (global+lock)");
  547. }
  548. }
  549. if (ZEND_VM_EXT_ISSET & flags) {
  550. if (!(opline->extended_value & ZEND_ISEMPTY)) {
  551. fprintf(stderr, " (isset)");
  552. } else {
  553. fprintf(stderr, " (empty)");
  554. }
  555. }
  556. if (ZEND_VM_EXT_ARRAY_INIT & flags) {
  557. fprintf(stderr, " %u", opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT);
  558. if (!(opline->extended_value & ZEND_ARRAY_NOT_PACKED)) {
  559. fprintf(stderr, " (packed)");
  560. }
  561. }
  562. if (ZEND_VM_EXT_REF & flags) {
  563. if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
  564. fprintf(stderr, " (ref)");
  565. }
  566. }
  567. }
  568. if (opline->op1_type == IS_CONST) {
  569. zend_dump_const(CRT_CONSTANT_EX(op_array, opline, opline->op1, (dump_flags & ZEND_DUMP_RT_CONSTANTS)));
  570. } else if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  571. if (ssa && ssa->ops) {
  572. int ssa_var_num = ssa->ops[opline - op_array->opcodes].op1_use;
  573. if (ssa_var_num >= 0) {
  574. fprintf(stderr, " ");
  575. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags);
  576. } else if (ssa->ops[opline - op_array->opcodes].op1_def < 0) {
  577. fprintf(stderr, " ");
  578. zend_dump_var(op_array, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var));
  579. }
  580. } else {
  581. fprintf(stderr, " ");
  582. zend_dump_var(op_array, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var));
  583. }
  584. if (ssa && ssa->ops) {
  585. int ssa_var_num = ssa->ops[opline - op_array->opcodes].op1_def;
  586. if (ssa_var_num >= 0) {
  587. fprintf(stderr, " -> ");
  588. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags);
  589. }
  590. }
  591. } else {
  592. uint32_t op1_flags = ZEND_VM_OP1_FLAGS(flags);
  593. if (ZEND_VM_OP_JMP_ADDR == (op1_flags & ZEND_VM_OP_MASK)) {
  594. if (b) {
  595. fprintf(stderr, " BB%d", b->successors[n++]);
  596. } else {
  597. fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes));
  598. }
  599. } else {
  600. zend_dump_unused_op(opline, opline->op1, op1_flags);
  601. }
  602. }
  603. if (opline->op2_type == IS_CONST) {
  604. zval *op = CRT_CONSTANT_EX(op_array, opline, opline->op2, (dump_flags & ZEND_DUMP_RT_CONSTANTS));
  605. if (opline->opcode == ZEND_SWITCH_LONG || opline->opcode == ZEND_SWITCH_STRING) {
  606. HashTable *jumptable = Z_ARRVAL_P(op);
  607. zend_string *key;
  608. zend_ulong num_key;
  609. zval *zv;
  610. ZEND_HASH_FOREACH_KEY_VAL(jumptable, num_key, key, zv) {
  611. if (key) {
  612. fprintf(stderr, " \"%s\":", ZSTR_VAL(key));
  613. } else {
  614. fprintf(stderr, " " ZEND_LONG_FMT ":", num_key);
  615. }
  616. if (b) {
  617. fprintf(stderr, " BB%d,", b->successors[n++]);
  618. } else {
  619. fprintf(stderr, " L%u,", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)));
  620. }
  621. } ZEND_HASH_FOREACH_END();
  622. fprintf(stderr, " default:");
  623. } else {
  624. zend_dump_const(op);
  625. }
  626. } else if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  627. if (ssa && ssa->ops) {
  628. int ssa_var_num = ssa->ops[opline - op_array->opcodes].op2_use;
  629. if (ssa_var_num >= 0) {
  630. fprintf(stderr, " ");
  631. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags);
  632. } else if (ssa->ops[opline - op_array->opcodes].op2_def < 0) {
  633. fprintf(stderr, " ");
  634. zend_dump_var(op_array, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var));
  635. }
  636. } else {
  637. fprintf(stderr, " ");
  638. zend_dump_var(op_array, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var));
  639. }
  640. if (ssa && ssa->ops) {
  641. int ssa_var_num = ssa->ops[opline - op_array->opcodes].op2_def;
  642. if (ssa_var_num >= 0) {
  643. fprintf(stderr, " -> ");
  644. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags);
  645. }
  646. }
  647. } else {
  648. uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags);
  649. if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) {
  650. if (opline->opcode != ZEND_CATCH || !(opline->extended_value & ZEND_LAST_CATCH)) {
  651. if (b) {
  652. fprintf(stderr, " BB%d", b->successors[n++]);
  653. } else {
  654. fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes));
  655. }
  656. }
  657. } else {
  658. zend_dump_unused_op(opline, opline->op2, op2_flags);
  659. }
  660. }
  661. if (ZEND_VM_EXT_JMP_ADDR == (flags & ZEND_VM_EXT_MASK)) {
  662. if (b) {
  663. fprintf(stderr, " BB%d", b->successors[n++]);
  664. } else {
  665. fprintf(stderr, " L%u", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
  666. }
  667. }
  668. if (opline->result_type == IS_CONST) {
  669. zend_dump_const(CRT_CONSTANT_EX(op_array, opline, opline->result, (dump_flags & ZEND_DUMP_RT_CONSTANTS)));
  670. } else if (ssa && ssa->ops && ssa->ops[opline - op_array->opcodes].result_use >= 0) {
  671. if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  672. if (ssa && ssa->ops) {
  673. int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_use;
  674. if (ssa_var_num >= 0) {
  675. fprintf(stderr, " ");
  676. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
  677. }
  678. } else {
  679. fprintf(stderr, " ");
  680. zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var));
  681. }
  682. if (ssa && ssa->ops) {
  683. int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def;
  684. if (ssa_var_num >= 0) {
  685. fprintf(stderr, " -> ");
  686. zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
  687. }
  688. }
  689. }
  690. }
  691. fprintf(stderr, "\n");
  692. }
  693. static void zend_dump_block_info(const zend_cfg *cfg, int n, uint32_t dump_flags)
  694. {
  695. zend_basic_block *b = cfg->blocks + n;
  696. fprintf(stderr, "BB%d:", n);
  697. if (b->flags & ZEND_BB_START) {
  698. fprintf(stderr, " start");
  699. }
  700. if (b->flags & ZEND_BB_FOLLOW) {
  701. fprintf(stderr, " follow");
  702. }
  703. if (b->flags & ZEND_BB_TARGET) {
  704. fprintf(stderr, " target");
  705. }
  706. if (b->flags & ZEND_BB_EXIT) {
  707. fprintf(stderr, " exit");
  708. }
  709. if (b->flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
  710. fprintf(stderr, " entry");
  711. }
  712. if (b->flags & ZEND_BB_TRY) {
  713. fprintf(stderr, " try");
  714. }
  715. if (b->flags & ZEND_BB_CATCH) {
  716. fprintf(stderr, " catch");
  717. }
  718. if (b->flags & ZEND_BB_FINALLY) {
  719. fprintf(stderr, " finally");
  720. }
  721. if (b->flags & ZEND_BB_FINALLY_END) {
  722. fprintf(stderr, " finally_end");
  723. }
  724. if (b->flags & ZEND_BB_GEN_VAR) {
  725. fprintf(stderr, " gen_var");
  726. }
  727. if (b->flags & ZEND_BB_KILL_VAR) {
  728. fprintf(stderr, " kill_var");
  729. }
  730. if (!(dump_flags & ZEND_DUMP_HIDE_UNREACHABLE) && !(b->flags & ZEND_BB_REACHABLE)) {
  731. fprintf(stderr, " unreachable");
  732. }
  733. if (b->flags & ZEND_BB_LOOP_HEADER) {
  734. fprintf(stderr, " loop_header");
  735. }
  736. if (b->flags & ZEND_BB_IRREDUCIBLE_LOOP) {
  737. fprintf(stderr, " irreducible");
  738. }
  739. if (b->len != 0) {
  740. fprintf(stderr, " lines=[%d-%d]", b->start, b->start + b->len - 1);
  741. } else {
  742. fprintf(stderr, " empty");
  743. }
  744. fprintf(stderr, "\n");
  745. if (b->predecessors_count) {
  746. int *p = cfg->predecessors + b->predecessor_offset;
  747. int *end = p + b->predecessors_count;
  748. fprintf(stderr, " ; from=(BB%d", *p);
  749. for (p++; p < end; p++) {
  750. fprintf(stderr, ", BB%d", *p);
  751. }
  752. fprintf(stderr, ")\n");
  753. }
  754. if (b->successors_count > 0) {
  755. int s;
  756. fprintf(stderr, " ; to=(BB%d", b->successors[0]);
  757. for (s = 1; s < b->successors_count; s++) {
  758. fprintf(stderr, ", BB%d", b->successors[s]);
  759. }
  760. fprintf(stderr, ")\n");
  761. }
  762. if (b->idom >= 0) {
  763. fprintf(stderr, " ; idom=BB%d\n", b->idom);
  764. }
  765. if (b->level >= 0) {
  766. fprintf(stderr, " ; level=%d\n", b->level);
  767. }
  768. if (b->loop_header >= 0) {
  769. fprintf(stderr, " ; loop_header=%d\n", b->loop_header);
  770. }
  771. if (b->children >= 0) {
  772. int j = b->children;
  773. fprintf(stderr, " ; children=(BB%d", j);
  774. j = cfg->blocks[j].next_child;
  775. while (j >= 0) {
  776. fprintf(stderr, ", BB%d", j);
  777. j = cfg->blocks[j].next_child;
  778. }
  779. fprintf(stderr, ")\n");
  780. }
  781. }
  782. static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_array, const zend_ssa *ssa, int n, uint32_t dump_flags)
  783. {
  784. zend_dump_block_info(cfg, n, dump_flags);
  785. if (ssa && ssa->blocks && ssa->blocks[n].phis) {
  786. zend_ssa_phi *p = ssa->blocks[n].phis;
  787. do {
  788. int j;
  789. fprintf(stderr, " ");
  790. zend_dump_ssa_var(op_array, ssa, p->ssa_var, 0, p->var, dump_flags);
  791. if (p->pi < 0) {
  792. fprintf(stderr, " = Phi(");
  793. for (j = 0; j < cfg->blocks[n].predecessors_count; j++) {
  794. if (j > 0) {
  795. fprintf(stderr, ", ");
  796. }
  797. zend_dump_ssa_var(op_array, ssa, p->sources[j], 0, p->var, dump_flags);
  798. }
  799. fprintf(stderr, ")\n");
  800. } else {
  801. fprintf(stderr, " = Pi<BB%d>(", p->pi);
  802. zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags);
  803. fprintf(stderr, " &");
  804. if (p->has_range_constraint) {
  805. zend_dump_range_constraint(op_array, ssa, &p->constraint.range, dump_flags);
  806. } else {
  807. zend_dump_type_constraint(op_array, ssa, &p->constraint.type, dump_flags);
  808. }
  809. fprintf(stderr, ")\n");
  810. }
  811. p = p->next;
  812. } while (p);
  813. }
  814. }
  815. void zend_dump_op_array_name(const zend_op_array *op_array)
  816. {
  817. zend_func_info *func_info = NULL;
  818. func_info = ZEND_FUNC_INFO(op_array);
  819. if (op_array->function_name) {
  820. if (op_array->scope && op_array->scope->name) {
  821. fprintf(stderr, "%s::%s", op_array->scope->name->val, op_array->function_name->val);
  822. } else {
  823. fprintf(stderr, "%s", op_array->function_name->val);
  824. }
  825. } else {
  826. fprintf(stderr, "%s", "$_main");
  827. }
  828. if (func_info && func_info->clone_num > 0) {
  829. fprintf(stderr, "_@_clone_%d", func_info->clone_num);
  830. }
  831. }
  832. void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data)
  833. {
  834. int i;
  835. const zend_cfg *cfg = NULL;
  836. const zend_ssa *ssa = NULL;
  837. zend_func_info *func_info = NULL;
  838. uint32_t func_flags = 0;
  839. if (dump_flags & (ZEND_DUMP_CFG|ZEND_DUMP_SSA)) {
  840. cfg = (const zend_cfg*)data;
  841. if (!cfg->blocks) {
  842. cfg = data = NULL;
  843. }
  844. }
  845. if (dump_flags & ZEND_DUMP_SSA) {
  846. ssa = (const zend_ssa*)data;
  847. }
  848. func_info = ZEND_FUNC_INFO(op_array);
  849. if (func_info) {
  850. func_flags = func_info->flags;
  851. }
  852. fprintf(stderr, "\n");
  853. zend_dump_op_array_name(op_array);
  854. fprintf(stderr, ": ; (lines=%d, args=%d",
  855. op_array->last,
  856. op_array->num_args);
  857. if (func_info && func_info->num_args >= 0) {
  858. fprintf(stderr, "/%d", func_info->num_args);
  859. }
  860. fprintf(stderr, ", vars=%d, tmps=%d", op_array->last_var, op_array->T);
  861. if (ssa) {
  862. fprintf(stderr, ", ssa_vars=%d", ssa->vars_count);
  863. }
  864. if (func_flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) {
  865. fprintf(stderr, ", dynamic");
  866. }
  867. if (func_flags & ZEND_FUNC_RECURSIVE) {
  868. fprintf(stderr, ", recursive");
  869. if (func_flags & ZEND_FUNC_RECURSIVE_DIRECTLY) {
  870. fprintf(stderr, " directly");
  871. }
  872. if (func_flags & ZEND_FUNC_RECURSIVE_INDIRECTLY) {
  873. fprintf(stderr, " indirectly");
  874. }
  875. }
  876. if (func_flags & ZEND_FUNC_IRREDUCIBLE) {
  877. fprintf(stderr, ", irreducable");
  878. }
  879. if (func_flags & ZEND_FUNC_NO_LOOPS) {
  880. fprintf(stderr, ", no_loops");
  881. }
  882. if (func_flags & ZEND_FUNC_HAS_EXTENDED_INFO) {
  883. fprintf(stderr, ", extended_info");
  884. }
  885. //TODO: this is useful only for JIT???
  886. #if 0
  887. if (info->flags & ZEND_JIT_FUNC_NO_IN_MEM_CVS) {
  888. fprintf(stderr, ", no_in_mem_cvs");
  889. }
  890. if (info->flags & ZEND_JIT_FUNC_NO_USED_ARGS) {
  891. fprintf(stderr, ", no_used_args");
  892. }
  893. if (info->flags & ZEND_JIT_FUNC_NO_SYMTAB) {
  894. fprintf(stderr, ", no_symtab");
  895. }
  896. if (info->flags & ZEND_JIT_FUNC_NO_FRAME) {
  897. fprintf(stderr, ", no_frame");
  898. }
  899. if (info->flags & ZEND_JIT_FUNC_INLINE) {
  900. fprintf(stderr, ", inline");
  901. }
  902. #endif
  903. if (func_info && func_info->return_value_used == 0) {
  904. fprintf(stderr, ", no_return_value");
  905. } else if (func_info && func_info->return_value_used == 1) {
  906. fprintf(stderr, ", return_value");
  907. }
  908. fprintf(stderr, ")\n");
  909. if (msg) {
  910. fprintf(stderr, " ; (%s)\n", msg);
  911. }
  912. fprintf(stderr, " ; %s:%u-%u\n", op_array->filename->val, op_array->line_start, op_array->line_end);
  913. if (func_info && func_info->num_args > 0) {
  914. uint32_t j;
  915. for (j = 0; j < MIN(op_array->num_args, func_info->num_args ); j++) {
  916. fprintf(stderr, " ; arg %d ", j);
  917. zend_dump_type_info(func_info->arg_info[j].info.type, func_info->arg_info[j].info.ce, func_info->arg_info[j].info.is_instanceof, dump_flags);
  918. zend_dump_range(&func_info->arg_info[j].info.range);
  919. fprintf(stderr, "\n");
  920. }
  921. }
  922. if (func_info) {
  923. fprintf(stderr, " ; return ");
  924. zend_dump_type_info(func_info->return_info.type, func_info->return_info.ce, func_info->return_info.is_instanceof, dump_flags);
  925. zend_dump_range(&func_info->return_info.range);
  926. fprintf(stderr, "\n");
  927. }
  928. if (ssa && ssa->var_info) {
  929. for (i = 0; i < op_array->last_var; i++) {
  930. fprintf(stderr, " ; ");
  931. zend_dump_ssa_var(op_array, ssa, i, IS_CV, i, dump_flags);
  932. fprintf(stderr, "\n");
  933. }
  934. }
  935. if (cfg) {
  936. int n;
  937. zend_basic_block *b;
  938. for (n = 0; n < cfg->blocks_count; n++) {
  939. b = cfg->blocks + n;
  940. if (!(dump_flags & ZEND_DUMP_HIDE_UNREACHABLE) || (b->flags & ZEND_BB_REACHABLE)) {
  941. const zend_op *opline;
  942. const zend_op *end;
  943. zend_dump_block_header(cfg, op_array, ssa, n, dump_flags);
  944. opline = op_array->opcodes + b->start;
  945. end = opline + b->len;
  946. while (opline < end) {
  947. zend_dump_op(op_array, b, opline, dump_flags, data);
  948. opline++;
  949. }
  950. }
  951. }
  952. if (op_array->last_live_range) {
  953. fprintf(stderr, "LIVE RANGES:\n");
  954. for (i = 0; i < op_array->last_live_range; i++) {
  955. if ((cfg->flags & ZEND_CFG_SPLIT_AT_LIVE_RANGES)) {
  956. fprintf(stderr, " %u: BB%u - BB%u ",
  957. EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
  958. cfg->map[op_array->live_range[i].start],
  959. cfg->map[op_array->live_range[i].end]);
  960. } else {
  961. fprintf(stderr, " %u: L%u - L%u ",
  962. EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
  963. op_array->live_range[i].start,
  964. op_array->live_range[i].end);
  965. }
  966. switch (op_array->live_range[i].var & ZEND_LIVE_MASK) {
  967. case ZEND_LIVE_TMPVAR:
  968. fprintf(stderr, "(tmp/var)\n");
  969. break;
  970. case ZEND_LIVE_LOOP:
  971. fprintf(stderr, "(loop)\n");
  972. break;
  973. case ZEND_LIVE_SILENCE:
  974. fprintf(stderr, "(silence)\n");
  975. break;
  976. case ZEND_LIVE_ROPE:
  977. fprintf(stderr, "(rope)\n");
  978. break;
  979. }
  980. }
  981. }
  982. if (op_array->last_try_catch) {
  983. fprintf(stderr, "EXCEPTION TABLE:\n");
  984. for (i = 0; i < op_array->last_try_catch; i++) {
  985. fprintf(stderr, " BB%u",
  986. cfg->map[op_array->try_catch_array[i].try_op]);
  987. if (op_array->try_catch_array[i].catch_op) {
  988. fprintf(stderr, ", BB%u",
  989. cfg->map[op_array->try_catch_array[i].catch_op]);
  990. } else {
  991. fprintf(stderr, ", -");
  992. }
  993. if (op_array->try_catch_array[i].finally_op) {
  994. fprintf(stderr, ", BB%u",
  995. cfg->map[op_array->try_catch_array[i].finally_op]);
  996. } else {
  997. fprintf(stderr, ", -");
  998. }
  999. if (op_array->try_catch_array[i].finally_end) {
  1000. fprintf(stderr, ", BB%u\n",
  1001. cfg->map[op_array->try_catch_array[i].finally_end]);
  1002. } else {
  1003. fprintf(stderr, ", -\n");
  1004. }
  1005. }
  1006. }
  1007. } else {
  1008. const zend_op *opline = op_array->opcodes;
  1009. const zend_op *end = opline + op_array->last;
  1010. while (opline < end) {
  1011. zend_dump_op(op_array, NULL, opline, dump_flags, data);
  1012. opline++;
  1013. }
  1014. if (op_array->last_live_range) {
  1015. fprintf(stderr, "LIVE RANGES:\n");
  1016. for (i = 0; i < op_array->last_live_range; i++) {
  1017. fprintf(stderr, " %u: L%u - L%u ",
  1018. EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
  1019. op_array->live_range[i].start,
  1020. op_array->live_range[i].end);
  1021. switch (op_array->live_range[i].var & ZEND_LIVE_MASK) {
  1022. case ZEND_LIVE_TMPVAR:
  1023. fprintf(stderr, "(tmp/var)\n");
  1024. break;
  1025. case ZEND_LIVE_LOOP:
  1026. fprintf(stderr, "(loop)\n");
  1027. break;
  1028. case ZEND_LIVE_SILENCE:
  1029. fprintf(stderr, "(silence)\n");
  1030. break;
  1031. case ZEND_LIVE_ROPE:
  1032. fprintf(stderr, "(rope)\n");
  1033. break;
  1034. }
  1035. }
  1036. }
  1037. if (op_array->last_try_catch) {
  1038. fprintf(stderr, "EXCEPTION TABLE:\n");
  1039. for (i = 0; i < op_array->last_try_catch; i++) {
  1040. fprintf(stderr, " L%u",
  1041. op_array->try_catch_array[i].try_op);
  1042. if (op_array->try_catch_array[i].catch_op) {
  1043. fprintf(stderr, ", L%u",
  1044. op_array->try_catch_array[i].catch_op);
  1045. } else {
  1046. fprintf(stderr, ", -");
  1047. }
  1048. if (op_array->try_catch_array[i].finally_op) {
  1049. fprintf(stderr, ", L%u",
  1050. op_array->try_catch_array[i].finally_op);
  1051. } else {
  1052. fprintf(stderr, ", -");
  1053. }
  1054. if (op_array->try_catch_array[i].finally_end) {
  1055. fprintf(stderr, ", L%u\n",
  1056. op_array->try_catch_array[i].finally_end);
  1057. } else {
  1058. fprintf(stderr, ", -\n");
  1059. }
  1060. }
  1061. }
  1062. }
  1063. }
  1064. void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg)
  1065. {
  1066. int j;
  1067. fprintf(stderr, "\nDOMINATORS-TREE for \"");
  1068. zend_dump_op_array_name(op_array);
  1069. fprintf(stderr, "\"\n");
  1070. for (j = 0; j < cfg->blocks_count; j++) {
  1071. zend_basic_block *b = cfg->blocks + j;
  1072. if (b->flags & ZEND_BB_REACHABLE) {
  1073. zend_dump_block_info(cfg, j, 0);
  1074. }
  1075. }
  1076. }
  1077. void zend_dump_variables(const zend_op_array *op_array)
  1078. {
  1079. int j;
  1080. fprintf(stderr, "\nCV Variables for \"");
  1081. zend_dump_op_array_name(op_array);
  1082. fprintf(stderr, "\"\n");
  1083. for (j = 0; j < op_array->last_var; j++) {
  1084. fprintf(stderr, " ");
  1085. zend_dump_var(op_array, IS_CV, j);
  1086. fprintf(stderr, "\n");
  1087. }
  1088. }
  1089. void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags)
  1090. {
  1091. int j;
  1092. if (ssa->vars) {
  1093. fprintf(stderr, "\nSSA Variable for \"");
  1094. zend_dump_op_array_name(op_array);
  1095. fprintf(stderr, "\"\n");
  1096. for (j = 0; j < ssa->vars_count; j++) {
  1097. fprintf(stderr, " ");
  1098. zend_dump_ssa_var(op_array, ssa, j, IS_CV, ssa->vars[j].var, dump_flags);
  1099. if (ssa->vars[j].scc >= 0) {
  1100. if (ssa->vars[j].scc_entry) {
  1101. fprintf(stderr, " *");
  1102. } else {
  1103. fprintf(stderr, " ");
  1104. }
  1105. fprintf(stderr, "SCC=%d", ssa->vars[j].scc);
  1106. }
  1107. fprintf(stderr, "\n");
  1108. }
  1109. }
  1110. }
  1111. static void zend_dump_var_set(const zend_op_array *op_array, const char *name, zend_bitset set)
  1112. {
  1113. int first = 1;
  1114. uint32_t i;
  1115. fprintf(stderr, " ; %s = {", name);
  1116. for (i = 0; i < op_array->last_var + op_array->T; i++) {
  1117. if (zend_bitset_in(set, i)) {
  1118. if (first) {
  1119. first = 0;
  1120. } else {
  1121. fprintf(stderr, ", ");
  1122. }
  1123. zend_dump_var(op_array, IS_CV, i);
  1124. }
  1125. }
  1126. fprintf(stderr, "}\n");
  1127. }
  1128. void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg)
  1129. {
  1130. int j;
  1131. fprintf(stderr, "\nVariable Liveness for \"");
  1132. zend_dump_op_array_name(op_array);
  1133. fprintf(stderr, "\"\n");
  1134. for (j = 0; j < cfg->blocks_count; j++) {
  1135. fprintf(stderr, " BB%d:\n", j);
  1136. zend_dump_var_set(op_array, "def", DFG_BITSET(dfg->def, dfg->size, j));
  1137. zend_dump_var_set(op_array, "use", DFG_BITSET(dfg->use, dfg->size, j));
  1138. zend_dump_var_set(op_array, "in ", DFG_BITSET(dfg->in, dfg->size, j));
  1139. zend_dump_var_set(op_array, "out", DFG_BITSET(dfg->out, dfg->size, j));
  1140. }
  1141. }
  1142. void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa)
  1143. {
  1144. int j;
  1145. zend_ssa_block *ssa_blocks = ssa->blocks;
  1146. int blocks_count = ssa->cfg.blocks_count;
  1147. fprintf(stderr, "\nSSA Phi() Placement for \"");
  1148. zend_dump_op_array_name(op_array);
  1149. fprintf(stderr, "\"\n");
  1150. for (j = 0; j < blocks_count; j++) {
  1151. if (ssa_blocks && ssa_blocks[j].phis) {
  1152. zend_ssa_phi *p = ssa_blocks[j].phis;
  1153. int first = 1;
  1154. fprintf(stderr, " BB%d:\n", j);
  1155. if (p->pi >= 0) {
  1156. fprintf(stderr, " ; pi={");
  1157. } else {
  1158. fprintf(stderr, " ; phi={");
  1159. }
  1160. do {
  1161. if (first) {
  1162. first = 0;
  1163. } else {
  1164. fprintf(stderr, ", ");
  1165. }
  1166. zend_dump_var(op_array, IS_CV, p->var);
  1167. p = p->next;
  1168. } while (p);
  1169. fprintf(stderr, "}\n");
  1170. }
  1171. }
  1172. }
  1173. /*
  1174. * Local variables:
  1175. * tab-width: 4
  1176. * c-basic-offset: 4
  1177. * indent-tabs-mode: t
  1178. * End:
  1179. */