/* +----------------------------------------------------------------------+ | Zend JIT | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov | | Xinchen Hui | +----------------------------------------------------------------------+ */ #include #include #if defined(__FreeBSD__) || defined(__DragonFly__) #include #elif defined(__HAIKU__) #include #endif #include #include #include "zend_API.h" #include "zend_elf.h" static void* zend_elf_read_sect(int fd, zend_elf_sectheader *sect) { void *s = emalloc(sect->size); if (lseek(fd, sect->ofs, SEEK_SET) < 0) { efree(s); return NULL; } if (read(fd, s, sect->size) != (ssize_t)sect->size) { efree(s); return NULL; } return s; } void zend_elf_load_symbols(void) { zend_elf_header hdr; zend_elf_sectheader sect; int i; #if defined(__linux__) int fd = open("/proc/self/exe", O_RDONLY); #elif defined(__NetBSD__) int fd = open("/proc/curproc/exe", O_RDONLY); #elif defined(__FreeBSD__) || defined(__DragonFly__) char path[PATH_MAX]; size_t pathlen = sizeof(path); int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; if (sysctl(mib, 4, path, &pathlen, NULL, 0) == -1) { return; } int fd = open(path, O_RDONLY); #elif defined(__sun) int fd = open("/proc/self/path/a.out", O_RDONLY); #elif defined(__HAIKU__) char path[PATH_MAX]; if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, path, sizeof(path)) != B_OK) { return; } int fd = open(path, O_RDONLY); #else // To complete eventually for other ELF platforms. // Otherwise APPLE is Mach-O int fd = -1; #endif if (fd >= 0) { if (read(fd, &hdr, sizeof(hdr)) == sizeof(hdr) && hdr.emagic[0] == '\177' && hdr.emagic[1] == 'E' && hdr.emagic[2] == 'L' && hdr.emagic[3] == 'F' && lseek(fd, hdr.shofs, SEEK_SET) >= 0) { for (i = 0; i < hdr.shnum; i++) { if (read(fd, §, sizeof(sect)) == sizeof(sect) && sect.type == ELFSECT_TYPE_SYMTAB) { uint32_t n, count = sect.size / sizeof(zend_elf_symbol); zend_elf_symbol *syms = zend_elf_read_sect(fd, §); char *str_tbl; if (syms) { if (lseek(fd, hdr.shofs + sect.link * sizeof(sect), SEEK_SET) >= 0 && read(fd, §, sizeof(sect)) == sizeof(sect) && (str_tbl = (char*)zend_elf_read_sect(fd, §)) != NULL) { for (n = 0; n < count; n++) { if (syms[n].name && (ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_FUNC /*|| ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_DATA*/) && (ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_LOCAL /*|| ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_GLOBAL*/)) { zend_jit_disasm_add_symbol(str_tbl + syms[n].name, syms[n].value, syms[n].size); } } efree(str_tbl); } efree(syms); } if (lseek(fd, hdr.shofs + (i + 1) * sizeof(sect), SEEK_SET) < 0) { break; } } } } close(fd); } }