summaryrefslogtreecommitdiff
path: root/ext/opcache/jit/zend_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache/jit/zend_elf.c')
-rw-r--r--ext/opcache/jit/zend_elf.c109
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, &sect, 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, &sect);
+ char *str_tbl;
+
+ if (syms) {
+ if (lseek(fd, hdr.shofs + sect.link * sizeof(sect), SEEK_SET) >= 0
+ && read(fd, &sect, sizeof(sect)) == sizeof(sect)
+ && (str_tbl = (char*)zend_elf_read_sect(fd, &sect)) != 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);
+ }
+}