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 +----------------------------------------------------------------------+
18 */
19
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #if defined(__FreeBSD__) || defined(__DragonFly__)
23 #include <sys/sysctl.h>
24 #elif defined(__HAIKU__)
25 #include <FindDirectory.h>
26 #endif
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include "zend_API.h"
31 #include "zend_elf.h"
32
zend_elf_read_sect(int fd,zend_elf_sectheader * sect)33 static void* zend_elf_read_sect(int fd, zend_elf_sectheader *sect)
34 {
35 void *s = emalloc(sect->size);
36
37 if (lseek(fd, sect->ofs, SEEK_SET) < 0) {
38 efree(s);
39 return NULL;
40 }
41 if (read(fd, s, sect->size) != (ssize_t)sect->size) {
42 efree(s);
43 return NULL;
44 }
45
46 return s;
47 }
48
zend_elf_load_symbols(void)49 void zend_elf_load_symbols(void)
50 {
51 zend_elf_header hdr;
52 zend_elf_sectheader sect;
53 int i;
54 #if defined(__linux__)
55 int fd = open("/proc/self/exe", O_RDONLY);
56 #elif defined(__NetBSD__)
57 int fd = open("/proc/curproc/exe", O_RDONLY);
58 #elif defined(__FreeBSD__) || defined(__DragonFly__)
59 char path[PATH_MAX];
60 size_t pathlen = sizeof(path);
61 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
62 if (sysctl(mib, 4, path, &pathlen, NULL, 0) == -1) {
63 return;
64 }
65 int fd = open(path, O_RDONLY);
66 #elif defined(__sun)
67 int fd = open("/proc/self/path/a.out", O_RDONLY);
68 #elif defined(__HAIKU__)
69 char path[PATH_MAX];
70 if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH,
71 NULL, path, sizeof(path)) != B_OK) {
72 return;
73 }
74
75 int fd = open(path, O_RDONLY);
76 #else
77 // To complete eventually for other ELF platforms.
78 // Otherwise APPLE is Mach-O
79 int fd = -1;
80 #endif
81
82 if (fd >= 0) {
83 if (read(fd, &hdr, sizeof(hdr)) == sizeof(hdr)
84 && hdr.emagic[0] == '\177'
85 && hdr.emagic[1] == 'E'
86 && hdr.emagic[2] == 'L'
87 && hdr.emagic[3] == 'F'
88 && lseek(fd, hdr.shofs, SEEK_SET) >= 0) {
89 for (i = 0; i < hdr.shnum; i++) {
90 if (read(fd, §, sizeof(sect)) == sizeof(sect)
91 && sect.type == ELFSECT_TYPE_SYMTAB) {
92 uint32_t n, count = sect.size / sizeof(zend_elf_symbol);
93 zend_elf_symbol *syms = zend_elf_read_sect(fd, §);
94 char *str_tbl;
95
96 if (syms) {
97 if (lseek(fd, hdr.shofs + sect.link * sizeof(sect), SEEK_SET) >= 0
98 && read(fd, §, sizeof(sect)) == sizeof(sect)
99 && (str_tbl = (char*)zend_elf_read_sect(fd, §)) != NULL) {
100 for (n = 0; n < count; n++) {
101 if (syms[n].name
102 && (ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_FUNC
103 /*|| ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_DATA*/)
104 && (ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_LOCAL
105 /*|| ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_GLOBAL*/)) {
106 zend_jit_disasm_add_symbol(str_tbl + syms[n].name, syms[n].value, syms[n].size);
107 }
108 }
109 efree(str_tbl);
110 }
111 efree(syms);
112 }
113 if (lseek(fd, hdr.shofs + (i + 1) * sizeof(sect), SEEK_SET) < 0) {
114 break;
115 }
116 }
117 }
118 }
119 close(fd);
120 }
121 }
122