xref: /PHP-8.0/ext/opcache/jit/zend_elf.c (revision d87d2f00)
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    | http://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, &sect, 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, &sect);
94 					char *str_tbl;
95 
96 					if (syms) {
97 						if (lseek(fd, hdr.shofs + sect.link * sizeof(sect), SEEK_SET) >= 0
98 						 && read(fd, &sect, sizeof(sect)) == sizeof(sect)
99 						 && (str_tbl = (char*)zend_elf_read_sect(fd, &sect)) != 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