php-src/ext/opcache/jit/zend_elf.c
Nikita Popov 9ff8d362b3 Merge branch 'PHP-8.0'
* PHP-8.0:
  opcache: more reliable way to get the current binary on solaris/illumos
2021-05-06 14:34:28 +02:00

122 lines
3.9 KiB
C

/*
+----------------------------------------------------------------------+
| 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: |
| https://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__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#elif defined(__HAIKU__)
#include <FindDirectory.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__) || 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, &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);
}
}