-
Notifications
You must be signed in to change notification settings - Fork 2
/
php_trace_dwfl.c
101 lines (78 loc) · 3.49 KB
/
php_trace_dwfl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| 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://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 |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: krakjoe |
+----------------------------------------------------------------------+
*/
#ifndef HAVE_PHP_TRACE_DWFL
#define HAVE_PHP_TRACE_DWFL
#include <php_trace.h>
#include <libelf.h>
#include <elfutils/libdwfl.h>
static char *php_trace_dwfl_debuginfo = NULL;
Dwfl_Callbacks php_trace_dwfl_callbacks = {
.find_elf = dwfl_linux_proc_find_elf,
.find_debuginfo = dwfl_standard_find_debuginfo,
.debuginfo_path = &php_trace_dwfl_debuginfo
};
static int php_trace_dwfl_get_module(Dwfl_Module *module, void **debugInfo, const char *moduleName, Dwarf_Addr start, void *ctx) {
GElf_Addr bias;
php_trace_context_t *context = (php_trace_context_t *) ctx;
Elf *elf = dwfl_module_getelf(module, &bias);
if (elf) {
Elf_Scn *section = NULL;
Elf_Data *data = NULL;
while ((section = elf_nextscn(elf, section))) {
GElf_Sym symbol;
GElf_Shdr header;
gelf_getshdr(section, &header);
if (header.sh_type == SHT_SYMTAB ||
header.sh_type == SHT_DYNSYM) {
int it = 0,
end = header.sh_size / header.sh_entsize;
data = elf_getdata(section, data);
while (it < end) {
char *symbolName;
size_t symbolLength;
gelf_getsym(data, it, &symbol);
symbolName = elf_strptr(elf, header.sh_link, symbol.st_name);
symbolLength = strlen(symbolName);
if (symbolLength == (sizeof("executor_globals")-1)) {
if (strncmp(symbolName, "executor_globals", symbolLength) == SUCCESS) {
context->executor = (void*) bias + symbol.st_value;
return DWARF_CB_ABORT;
}
}
it++;
}
}
}
}
return DWARF_CB_OK;
}
int php_trace_dwfl_init(php_trace_context_t *context) {
Dwfl* dwfl = dwfl_begin(&php_trace_dwfl_callbacks);
if (!dwfl) {
return FAILURE;
}
if (dwfl_linux_proc_report(dwfl, context->pid) != SUCCESS) {
dwfl_end(dwfl);
return FAILURE;
}
dwfl_getmodules(dwfl, php_trace_dwfl_get_module, context, 0);
dwfl_report_end(dwfl, NULL, NULL);
dwfl_end(dwfl);
return SUCCESS;
}
#endif