zend_jit_disasm.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend JIT |
  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. | Xinchen Hui <laruence@php.net> |
  17. | Hao Sun <hao.sun@arm.com> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifdef HAVE_CAPSTONE
  21. # define HAVE_DISASM 1
  22. # include <capstone/capstone.h>
  23. # define HAVE_CAPSTONE_ITER 1
  24. #elif ZEND_JIT_TARGET_X86
  25. # define HAVE_DISASM 1
  26. # define DISASM_INTEL_SYNTAX 0
  27. # include "jit/libudis86/itab.c"
  28. # include "jit/libudis86/decode.c"
  29. # include "jit/libudis86/syn.c"
  30. # if DISASM_INTEL_SYNTAX
  31. # include "jit/libudis86/syn-intel.c"
  32. # else
  33. # include "jit/libudis86/syn-att.c"
  34. # endif
  35. # include "jit/libudis86/udis86.c"
  36. #endif /* HAVE_CAPSTONE */
  37. #ifdef HAVE_DISASM
  38. static void zend_jit_disasm_add_symbol(const char *name,
  39. uint64_t addr,
  40. uint64_t size);
  41. #ifndef _WIN32
  42. # include "jit/zend_elf.c"
  43. #endif
  44. #include "zend_sort.h"
  45. #ifndef _GNU_SOURCE
  46. # define _GNU_SOURCE
  47. #endif
  48. #ifndef _WIN32
  49. #include <dlfcn.h>
  50. #endif
  51. struct _sym_node {
  52. uint64_t addr;
  53. uint64_t end;
  54. struct _sym_node *parent;
  55. struct _sym_node *child[2];
  56. unsigned char info;
  57. char name[1];
  58. };
  59. static void zend_syms_rotateleft(zend_sym_node *p) {
  60. zend_sym_node *r = p->child[1];
  61. p->child[1] = r->child[0];
  62. if (r->child[0]) {
  63. r->child[0]->parent = p;
  64. }
  65. r->parent = p->parent;
  66. if (p->parent == NULL) {
  67. JIT_G(symbols) = r;
  68. } else if (p->parent->child[0] == p) {
  69. p->parent->child[0] = r;
  70. } else {
  71. p->parent->child[1] = r;
  72. }
  73. r->child[0] = p;
  74. p->parent = r;
  75. }
  76. static void zend_syms_rotateright(zend_sym_node *p) {
  77. zend_sym_node *l = p->child[0];
  78. p->child[0] = l->child[1];
  79. if (l->child[1]) {
  80. l->child[1]->parent = p;
  81. }
  82. l->parent = p->parent;
  83. if (p->parent == NULL) {
  84. JIT_G(symbols) = l;
  85. } else if (p->parent->child[1] == p) {
  86. p->parent->child[1] = l;
  87. } else {
  88. p->parent->child[0] = l;
  89. }
  90. l->child[1] = p;
  91. p->parent = l;
  92. }
  93. static void zend_jit_disasm_add_symbol(const char *name,
  94. uint64_t addr,
  95. uint64_t size)
  96. {
  97. zend_sym_node *sym;
  98. size_t len = strlen(name);
  99. sym = malloc(sizeof(zend_sym_node) + len + 1);
  100. if (!sym) {
  101. return;
  102. }
  103. sym->addr = addr;
  104. sym->end = (addr + size - 1);
  105. memcpy((char*)&sym->name, name, len + 1);
  106. sym->parent = sym->child[0] = sym->child[1] = NULL;
  107. sym->info = 1;
  108. if (JIT_G(symbols)) {
  109. zend_sym_node *node = JIT_G(symbols);
  110. /* insert it into rbtree */
  111. do {
  112. if (sym->addr > node->addr) {
  113. ZEND_ASSERT(sym->addr > (node->end));
  114. if (node->child[1]) {
  115. node = node->child[1];
  116. } else {
  117. node->child[1] = sym;
  118. sym->parent = node;
  119. break;
  120. }
  121. } else if (sym->addr < node->addr) {
  122. if (node->child[0]) {
  123. node = node->child[0];
  124. } else {
  125. node->child[0] = sym;
  126. sym->parent = node;
  127. break;
  128. }
  129. } else {
  130. ZEND_ASSERT(sym->addr == node->addr);
  131. if (strcmp(name, node->name) == 0 && sym->end < node->end) {
  132. /* reduce size of the existing symbol */
  133. node->end = sym->end;
  134. }
  135. free(sym);
  136. return;
  137. }
  138. } while (1);
  139. /* fix rbtree after instering */
  140. while (sym && sym != JIT_G(symbols) && sym->parent->info == 1) {
  141. if (sym->parent == sym->parent->parent->child[0]) {
  142. node = sym->parent->parent->child[1];
  143. if (node && node->info == 1) {
  144. sym->parent->info = 0;
  145. node->info = 0;
  146. sym->parent->parent->info = 1;
  147. sym = sym->parent->parent;
  148. } else {
  149. if (sym == sym->parent->child[1]) {
  150. sym = sym->parent;
  151. zend_syms_rotateleft(sym);
  152. }
  153. sym->parent->info = 0;
  154. sym->parent->parent->info = 1;
  155. zend_syms_rotateright(sym->parent->parent);
  156. }
  157. } else {
  158. node = sym->parent->parent->child[0];
  159. if (node && node->info == 1) {
  160. sym->parent->info = 0;
  161. node->info = 0;
  162. sym->parent->parent->info = 1;
  163. sym = sym->parent->parent;
  164. } else {
  165. if (sym == sym->parent->child[0]) {
  166. sym = sym->parent;
  167. zend_syms_rotateright(sym);
  168. }
  169. sym->parent->info = 0;
  170. sym->parent->parent->info = 1;
  171. zend_syms_rotateleft(sym->parent->parent);
  172. }
  173. }
  174. }
  175. } else {
  176. JIT_G(symbols) = sym;
  177. }
  178. JIT_G(symbols)->info = 0;
  179. }
  180. static void zend_jit_disasm_destroy_symbols(zend_sym_node *n) {
  181. if (n) {
  182. if (n->child[0]) {
  183. zend_jit_disasm_destroy_symbols(n->child[0]);
  184. }
  185. if (n->child[1]) {
  186. zend_jit_disasm_destroy_symbols(n->child[1]);
  187. }
  188. free(n);
  189. }
  190. }
  191. static const char* zend_jit_disasm_find_symbol(uint64_t addr,
  192. int64_t *offset) {
  193. zend_sym_node *node = JIT_G(symbols);
  194. while (node) {
  195. if (addr < node->addr) {
  196. node = node->child[0];
  197. } else if (addr > node->end) {
  198. node = node->child[1];
  199. } else {
  200. *offset = addr - node->addr;
  201. return node->name;
  202. }
  203. }
  204. return NULL;
  205. }
  206. #ifdef HAVE_CAPSTONE
  207. static uint64_t zend_jit_disasm_branch_target(csh cs, const cs_insn *insn)
  208. {
  209. unsigned int i;
  210. #if ZEND_JIT_TARGET_X86
  211. if (cs_insn_group(cs, insn, X86_GRP_JUMP)) {
  212. for (i = 0; i < insn->detail->x86.op_count; i++) {
  213. if (insn->detail->x86.operands[i].type == X86_OP_IMM) {
  214. return insn->detail->x86.operands[i].imm;
  215. }
  216. }
  217. }
  218. #elif ZEND_JIT_TARGET_ARM64
  219. if (cs_insn_group(cs, insn, ARM64_GRP_JUMP)
  220. || insn->id == ARM64_INS_BL
  221. || insn->id == ARM64_INS_ADR) {
  222. for (i = 0; i < insn->detail->arm64.op_count; i++) {
  223. if (insn->detail->arm64.operands[i].type == ARM64_OP_IMM)
  224. return insn->detail->arm64.operands[i].imm;
  225. }
  226. }
  227. #endif
  228. return 0;
  229. }
  230. #endif
  231. static const char* zend_jit_disasm_resolver(
  232. #ifndef HAVE_CAPSTONE
  233. struct ud *ud,
  234. #endif
  235. uint64_t addr,
  236. int64_t *offset)
  237. {
  238. #ifndef _WIN32
  239. # ifndef HAVE_CAPSTONE
  240. ((void)ud);
  241. # endif
  242. const char *name;
  243. void *a = (void*)(zend_uintptr_t)(addr);
  244. Dl_info info;
  245. name = zend_jit_disasm_find_symbol(addr, offset);
  246. if (name) {
  247. return name;
  248. }
  249. if (dladdr(a, &info)
  250. && info.dli_sname != NULL
  251. && info.dli_saddr == a) {
  252. return info.dli_sname;
  253. }
  254. #else
  255. const char *name;
  256. name = zend_jit_disasm_find_symbol(addr, offset);
  257. if (name) {
  258. return name;
  259. }
  260. #endif
  261. return NULL;
  262. }
  263. static int zend_jit_cmp_labels(Bucket *b1, Bucket *b2)
  264. {
  265. return ((b1->h > b2->h) > 0) ? 1 : -1;
  266. }
  267. static int zend_jit_disasm(const char *name,
  268. const char *filename,
  269. const zend_op_array *op_array,
  270. zend_cfg *cfg,
  271. const void *start,
  272. size_t size)
  273. {
  274. const void *end = (void *)((char *)start + size);
  275. zval zv, *z;
  276. zend_long n, m;
  277. HashTable labels;
  278. uint64_t addr;
  279. int b;
  280. #ifdef HAVE_CAPSTONE
  281. csh cs;
  282. cs_insn *insn;
  283. # ifdef HAVE_CAPSTONE_ITER
  284. const uint8_t *cs_code;
  285. size_t cs_size;
  286. uint64_t cs_addr;
  287. # else
  288. size_t count, i;
  289. # endif
  290. const char *sym;
  291. int64_t offset = 0;
  292. char *p, *q, *r;
  293. #else
  294. struct ud ud;
  295. const struct ud_operand *op;
  296. #endif
  297. #ifdef HAVE_CAPSTONE
  298. # if ZEND_JIT_TARGET_X86
  299. # if defined(__x86_64__) || defined(_WIN64)
  300. if (cs_open(CS_ARCH_X86, CS_MODE_64, &cs) != CS_ERR_OK)
  301. return 0;
  302. # else
  303. if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs) != CS_ERR_OK)
  304. return 0;
  305. # endif
  306. cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
  307. # if DISASM_INTEL_SYNTAX
  308. cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
  309. # else
  310. cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
  311. # endif
  312. # elif ZEND_JIT_TARGET_ARM64
  313. if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &cs) != CS_ERR_OK)
  314. return 0;
  315. cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
  316. cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
  317. # endif
  318. #else
  319. ud_init(&ud);
  320. # if defined(__x86_64__) || defined(_WIN64)
  321. ud_set_mode(&ud, 64);
  322. # else
  323. ud_set_mode(&ud, 32);
  324. # endif
  325. # if DISASM_INTEL_SYNTAX
  326. ud_set_syntax(&ud, UD_SYN_INTEL);
  327. # else
  328. ud_set_syntax(&ud, UD_SYN_ATT);
  329. # endif
  330. ud_set_sym_resolver(&ud, zend_jit_disasm_resolver);
  331. #endif /* HAVE_CAPSTONE */
  332. if (name) {
  333. fprintf(stderr, "%s: ; (%s)\n", name, filename ? filename : "unknown");
  334. }
  335. #ifndef HAVE_CAPSTONE
  336. ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
  337. ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
  338. #endif
  339. zend_hash_init(&labels, 8, NULL, NULL, 0);
  340. if (op_array && cfg) {
  341. ZVAL_FALSE(&zv);
  342. for (b = 0; b < cfg->blocks_count; b++) {
  343. if (cfg->blocks[b].flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
  344. addr = (uint64_t)(uintptr_t)op_array->opcodes[cfg->blocks[b].start].handler;
  345. if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
  346. zend_hash_index_add(&labels, addr, &zv);
  347. }
  348. }
  349. }
  350. }
  351. #ifdef HAVE_CAPSTONE
  352. ZVAL_TRUE(&zv);
  353. # ifdef HAVE_CAPSTONE_ITER
  354. cs_code = start;
  355. cs_size = (uint8_t*)end - (uint8_t*)start;
  356. cs_addr = (uint64_t)(uintptr_t)cs_code;
  357. insn = cs_malloc(cs);
  358. while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
  359. if ((addr = zend_jit_disasm_branch_target(cs, insn))) {
  360. # else
  361. count = cs_disasm(cs, start, (uint8_t*)end - (uint8_t*)start, (uintptr_t)start, 0, &insn);
  362. for (i = 0; i < count; i++) {
  363. if ((addr = zend_jit_disasm_branch_target(cs, &(insn[i])))) {
  364. # endif
  365. if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
  366. zend_hash_index_add(&labels, addr, &zv);
  367. }
  368. }
  369. }
  370. #else
  371. ZVAL_TRUE(&zv);
  372. while (ud_disassemble(&ud)) {
  373. op = ud_insn_opr(&ud, 0);
  374. if (op && op->type == UD_OP_JIMM) {
  375. addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
  376. if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
  377. zend_hash_index_add(&labels, addr, &zv);
  378. }
  379. }
  380. }
  381. #endif
  382. zend_hash_sort(&labels, zend_jit_cmp_labels, 0);
  383. /* label numbering */
  384. n = 0; m = 0;
  385. ZEND_HASH_FOREACH_VAL(&labels, z) {
  386. if (Z_TYPE_P(z) == IS_FALSE) {
  387. m--;
  388. ZVAL_LONG(z, m);
  389. } else {
  390. n++;
  391. ZVAL_LONG(z, n);
  392. }
  393. } ZEND_HASH_FOREACH_END();
  394. #ifdef HAVE_CAPSTONE
  395. # ifdef HAVE_CAPSTONE_ITER
  396. cs_code = start;
  397. cs_size = (uint8_t*)end - (uint8_t*)start;
  398. cs_addr = (uint64_t)(uintptr_t)cs_code;
  399. while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
  400. z = zend_hash_index_find(&labels, insn->address);
  401. # else
  402. for (i = 0; i < count; i++) {
  403. z = zend_hash_index_find(&labels, insn[i].address);
  404. # endif
  405. if (z) {
  406. if (Z_LVAL_P(z) < 0) {
  407. fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
  408. } else {
  409. fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
  410. }
  411. }
  412. # ifdef HAVE_CAPSTONE_ITER
  413. if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
  414. fprintf(stderr, " %" PRIx64 ":", insn->address);
  415. }
  416. fprintf(stderr, "\t%s ", insn->mnemonic);
  417. p = insn->op_str;
  418. # else
  419. if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
  420. fprintf(stderr, " %" PRIx64 ":", insn[i].address);
  421. }
  422. fprintf(stderr, "\t%s ", insn[i].mnemonic);
  423. p = insn[i].op_str;
  424. # endif
  425. /* Try to replace the target addresses with a symbols */
  426. while ((q = strchr(p, 'x')) != NULL) {
  427. if (p != q && *(q-1) == '0') {
  428. r = q + 1;
  429. addr = 0;
  430. while (1) {
  431. if (*r >= '0' && *r <= '9') {
  432. addr = addr * 16 + (*r - '0');
  433. } else if (*r >= 'A' && *r <= 'F') {
  434. addr = addr * 16 + (*r - 'A' + 10);
  435. } else if (*r >= 'a' && *r <= 'f') {
  436. addr = addr * 16 + (*r - 'a' + 10);
  437. } else {
  438. break;
  439. }
  440. r++;
  441. }
  442. if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
  443. if ((z = zend_hash_index_find(&labels, addr))) {
  444. if (Z_LVAL_P(z) < 0) {
  445. fwrite(p, 1, q - p - 1, stderr);
  446. fprintf(stderr, ".ENTRY" ZEND_LONG_FMT, -Z_LVAL_P(z));
  447. } else {
  448. fwrite(p, 1, q - p - 1, stderr);
  449. fprintf(stderr, ".L" ZEND_LONG_FMT, Z_LVAL_P(z));
  450. }
  451. } else {
  452. fwrite(p, 1, r - p, stderr);
  453. }
  454. } else if ((sym = zend_jit_disasm_resolver(addr, &offset))) {
  455. fwrite(p, 1, q - p - 1, stderr);
  456. fputs(sym, stderr);
  457. if (offset != 0) {
  458. if (offset > 0) {
  459. fprintf(stderr, "+%" PRIx64, offset);
  460. } else {
  461. fprintf(stderr, "-%" PRIx64, offset);
  462. }
  463. }
  464. } else {
  465. fwrite(p, 1, r - p, stderr);
  466. }
  467. p = r;
  468. } else {
  469. fwrite(p, 1, q - p + 1, stderr);
  470. p = q + 1;
  471. }
  472. }
  473. fprintf(stderr, "%s\n", p);
  474. }
  475. # ifdef HAVE_CAPSTONE_ITER
  476. cs_free(insn, 1);
  477. # else
  478. cs_free(insn, count);
  479. # endif
  480. #else
  481. ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
  482. ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
  483. while (ud_disassemble(&ud)) {
  484. addr = ud_insn_off(&ud);
  485. z = zend_hash_index_find(&labels, addr);
  486. if (z) {
  487. if (Z_LVAL_P(z) < 0) {
  488. fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
  489. } else {
  490. fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
  491. }
  492. }
  493. op = ud_insn_opr(&ud, 0);
  494. if (op && op->type == UD_OP_JIMM) {
  495. addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
  496. if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
  497. z = zend_hash_index_find(&labels, addr);
  498. if (z) {
  499. const char *str = ud_insn_asm(&ud);
  500. int len;
  501. len = 0;
  502. while (str[len] != 0 && str[len] != ' ' && str[len] != '\t') {
  503. len++;
  504. }
  505. if (str[len] != 0) {
  506. while (str[len] == ' ' || str[len] == '\t') {
  507. len++;
  508. }
  509. if (Z_LVAL_P(z) < 0) {
  510. fprintf(stderr, "\t%.*s.ENTRY" ZEND_LONG_FMT "\n", len, str, -Z_LVAL_P(z));
  511. } else {
  512. fprintf(stderr, "\t%.*s.L" ZEND_LONG_FMT "\n", len, str, Z_LVAL_P(z));
  513. }
  514. continue;
  515. }
  516. }
  517. }
  518. }
  519. if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
  520. fprintf(stderr, " %" PRIx64 ":", ud_insn_off(&ud));
  521. }
  522. fprintf(stderr, "\t%s\n", ud_insn_asm(&ud));
  523. }
  524. #endif
  525. fprintf(stderr, "\n");
  526. zend_hash_destroy(&labels);
  527. #ifdef HAVE_CAPSTONE
  528. cs_close(&cs);
  529. #endif
  530. return 1;
  531. }
  532. static int zend_jit_disasm_init(void)
  533. {
  534. #ifndef ZTS
  535. #define REGISTER_EG(n) \
  536. zend_jit_disasm_add_symbol("EG("#n")", \
  537. (uint64_t)(uintptr_t)&executor_globals.n, sizeof(executor_globals.n))
  538. REGISTER_EG(uninitialized_zval);
  539. REGISTER_EG(exception);
  540. REGISTER_EG(vm_interrupt);
  541. REGISTER_EG(exception_op);
  542. REGISTER_EG(timed_out);
  543. REGISTER_EG(current_execute_data);
  544. REGISTER_EG(vm_stack_top);
  545. REGISTER_EG(vm_stack_end);
  546. REGISTER_EG(symbol_table);
  547. REGISTER_EG(jit_trace_num);
  548. #undef REGISTER_EG
  549. #define REGISTER_CG(n) \
  550. zend_jit_disasm_add_symbol("CG("#n")", \
  551. (uint64_t)(uintptr_t)&compiler_globals.n, sizeof(compiler_globals.n))
  552. REGISTER_CG(map_ptr_base);
  553. #undef REGISTER_CG
  554. #endif
  555. /* Register JIT helper functions */
  556. #define REGISTER_HELPER(n) \
  557. zend_jit_disasm_add_symbol(#n, \
  558. (uint64_t)(uintptr_t)n, sizeof(void*));
  559. REGISTER_HELPER(memcmp);
  560. REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper);
  561. REGISTER_HELPER(zend_jit_find_func_helper);
  562. REGISTER_HELPER(zend_jit_find_ns_func_helper);
  563. REGISTER_HELPER(zend_jit_find_method_helper);
  564. REGISTER_HELPER(zend_jit_find_method_tmp_helper);
  565. REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
  566. REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
  567. REGISTER_HELPER(zend_jit_invalid_method_call);
  568. REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
  569. REGISTER_HELPER(zend_jit_unref_helper);
  570. REGISTER_HELPER(zend_jit_extend_stack_helper);
  571. REGISTER_HELPER(zend_jit_int_extend_stack_helper);
  572. REGISTER_HELPER(zend_jit_leave_nested_func_helper);
  573. REGISTER_HELPER(zend_jit_leave_top_func_helper);
  574. REGISTER_HELPER(zend_jit_leave_func_helper);
  575. REGISTER_HELPER(zend_jit_symtable_find);
  576. REGISTER_HELPER(zend_jit_hash_index_lookup_rw_no_packed);
  577. REGISTER_HELPER(zend_jit_hash_index_lookup_rw);
  578. REGISTER_HELPER(zend_jit_hash_lookup_rw);
  579. REGISTER_HELPER(zend_jit_symtable_lookup_rw);
  580. REGISTER_HELPER(zend_jit_symtable_lookup_w);
  581. REGISTER_HELPER(zend_jit_undefined_op_helper);
  582. REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
  583. REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
  584. REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
  585. REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
  586. REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
  587. REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
  588. REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
  589. REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
  590. REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
  591. REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
  592. REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
  593. REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
  594. // REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
  595. REGISTER_HELPER(zend_jit_assign_dim_helper);
  596. REGISTER_HELPER(zend_jit_assign_dim_op_helper);
  597. REGISTER_HELPER(zend_jit_fast_assign_concat_helper);
  598. REGISTER_HELPER(zend_jit_fast_concat_helper);
  599. REGISTER_HELPER(zend_jit_fast_concat_tmp_helper);
  600. REGISTER_HELPER(zend_jit_isset_dim_helper);
  601. REGISTER_HELPER(zend_jit_free_call_frame);
  602. REGISTER_HELPER(zend_jit_fetch_global_helper);
  603. REGISTER_HELPER(zend_jit_verify_arg_slow);
  604. REGISTER_HELPER(zend_jit_verify_return_slow);
  605. REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
  606. REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
  607. REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
  608. REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
  609. REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
  610. REGISTER_HELPER(zend_jit_check_array_promotion);
  611. REGISTER_HELPER(zend_jit_create_typed_ref);
  612. REGISTER_HELPER(zend_jit_extract_helper);
  613. REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
  614. REGISTER_HELPER(zend_jit_copy_extra_args_helper);
  615. REGISTER_HELPER(zend_jit_deprecated_helper);
  616. REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
  617. REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
  618. REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
  619. REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref);
  620. REGISTER_HELPER(zend_jit_pre_inc_typed_ref);
  621. REGISTER_HELPER(zend_jit_pre_dec_typed_ref);
  622. REGISTER_HELPER(zend_jit_post_inc_typed_ref);
  623. REGISTER_HELPER(zend_jit_post_dec_typed_ref);
  624. REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
  625. REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp);
  626. REGISTER_HELPER(zend_jit_only_vars_by_reference);
  627. REGISTER_HELPER(zend_jit_invalid_array_access);
  628. REGISTER_HELPER(zend_jit_invalid_property_read);
  629. REGISTER_HELPER(zend_jit_invalid_property_write);
  630. REGISTER_HELPER(zend_jit_invalid_property_incdec);
  631. REGISTER_HELPER(zend_jit_invalid_property_assign);
  632. REGISTER_HELPER(zend_jit_invalid_property_assign_op);
  633. REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
  634. REGISTER_HELPER(zend_jit_pre_inc);
  635. REGISTER_HELPER(zend_jit_pre_dec);
  636. REGISTER_HELPER(zend_runtime_jit);
  637. REGISTER_HELPER(zend_jit_hot_func);
  638. REGISTER_HELPER(zend_jit_check_constant);
  639. REGISTER_HELPER(zend_jit_get_constant);
  640. REGISTER_HELPER(zend_jit_array_free);
  641. REGISTER_HELPER(zend_jit_zval_array_dup);
  642. REGISTER_HELPER(zend_jit_add_arrays_helper);
  643. REGISTER_HELPER(zend_jit_assign_obj_helper);
  644. REGISTER_HELPER(zend_jit_assign_obj_op_helper);
  645. REGISTER_HELPER(zend_jit_assign_to_typed_prop);
  646. REGISTER_HELPER(zend_jit_assign_op_to_typed_prop);
  647. REGISTER_HELPER(zend_jit_inc_typed_prop);
  648. REGISTER_HELPER(zend_jit_dec_typed_prop);
  649. REGISTER_HELPER(zend_jit_pre_inc_typed_prop);
  650. REGISTER_HELPER(zend_jit_pre_dec_typed_prop);
  651. REGISTER_HELPER(zend_jit_post_inc_typed_prop);
  652. REGISTER_HELPER(zend_jit_post_dec_typed_prop);
  653. REGISTER_HELPER(zend_jit_pre_inc_obj_helper);
  654. REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
  655. REGISTER_HELPER(zend_jit_post_inc_obj_helper);
  656. REGISTER_HELPER(zend_jit_post_dec_obj_helper);
  657. REGISTER_HELPER(zend_jit_rope_end);
  658. #if (PHP_VERSION_ID <= 80100) && (SIZEOF_SIZE_T == 4)
  659. REGISTER_HELPER(zval_jit_update_constant_ex);
  660. #endif
  661. REGISTER_HELPER(zend_jit_free_trampoline_helper);
  662. REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper);
  663. #undef REGISTER_HELPER
  664. #ifndef _WIN32
  665. zend_elf_load_symbols();
  666. #endif
  667. if (zend_vm_kind() == ZEND_VM_KIND_HYBRID) {
  668. zend_op opline;
  669. memset(&opline, 0, sizeof(opline));
  670. opline.opcode = ZEND_DO_UCALL;
  671. opline.result_type = IS_UNUSED;
  672. zend_vm_set_opcode_handler(&opline);
  673. zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  674. opline.opcode = ZEND_DO_UCALL;
  675. opline.result_type = IS_VAR;
  676. zend_vm_set_opcode_handler(&opline);
  677. zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  678. opline.opcode = ZEND_DO_FCALL_BY_NAME;
  679. opline.result_type = IS_UNUSED;
  680. zend_vm_set_opcode_handler(&opline);
  681. zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  682. opline.opcode = ZEND_DO_FCALL_BY_NAME;
  683. opline.result_type = IS_VAR;
  684. zend_vm_set_opcode_handler(&opline);
  685. zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  686. opline.opcode = ZEND_DO_FCALL;
  687. opline.result_type = IS_UNUSED;
  688. zend_vm_set_opcode_handler(&opline);
  689. zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  690. opline.opcode = ZEND_DO_FCALL;
  691. opline.result_type = IS_VAR;
  692. zend_vm_set_opcode_handler(&opline);
  693. zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  694. opline.opcode = ZEND_RETURN;
  695. opline.op1_type = IS_CONST;
  696. zend_vm_set_opcode_handler(&opline);
  697. zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CONST_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  698. opline.opcode = ZEND_RETURN;
  699. opline.op1_type = IS_TMP_VAR;
  700. zend_vm_set_opcode_handler(&opline);
  701. zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_TMP_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  702. opline.opcode = ZEND_RETURN;
  703. opline.op1_type = IS_VAR;
  704. zend_vm_set_opcode_handler(&opline);
  705. zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_VAR_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  706. opline.opcode = ZEND_RETURN;
  707. opline.op1_type = IS_CV;
  708. zend_vm_set_opcode_handler(&opline);
  709. zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CV_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
  710. zend_jit_disasm_add_symbol("ZEND_HYBRID_HALT_LABEL", (uint64_t)(uintptr_t)zend_jit_halt_op->handler, sizeof(void*));
  711. }
  712. return 1;
  713. }
  714. static void zend_jit_disasm_shutdown(void)
  715. {
  716. if (JIT_G(symbols)) {
  717. zend_jit_disasm_destroy_symbols(JIT_G(symbols));
  718. JIT_G(symbols) = NULL;
  719. }
  720. }
  721. #endif /* HAVE_DISASM */