zend_dump.c 36 KB

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