diff options
Diffstat (limited to 'ext/opcache/jit/zend_elf.c')
| -rw-r--r-- | ext/opcache/jit/zend_elf.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/ext/opcache/jit/zend_elf.c b/ext/opcache/jit/zend_elf.c new file mode 100644 index 0000000000..f5180e0a96 --- /dev/null +++ b/ext/opcache/jit/zend_elf.c @@ -0,0 +1,109 @@ +/* + +----------------------------------------------------------------------+ + | 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 <dmitry@php.net> | + | Xinchen Hui <laruence@php.net> | + +----------------------------------------------------------------------+ +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#if defined(__FreeBSD__) +#include <sys/sysctl.h> +#endif +#include <fcntl.h> +#include <unistd.h> + +#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__) + 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); +#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); + } +} |
