Completed
Push — master ( a823ea...a54744 )
by Shinji
19s queued 12s
created

PhpGlobalsFinder::getSymbolReader()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
nc 2
nop 1
dl 0
loc 6
c 0
b 0
f 0
cc 2
rs 10
1
<?php
2
3
/**
4
 * This file is part of the sj-i/php-profiler package.
5
 *
6
 * (c) sji <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace PhpProfiler\ProcessReader;
15
16
use PhpProfiler\Lib\Binary\BinaryReader;
17
use PhpProfiler\Lib\Binary\CDataByteReader;
18
use PhpProfiler\Lib\Elf\Parser\ElfParserException;
19
use PhpProfiler\Lib\Elf\Process\ProcessSymbolReaderException;
20
use PhpProfiler\Lib\Elf\Process\ProcessSymbolReaderInterface;
21
use PhpProfiler\Lib\Elf\Tls\TlsFinderException;
22
use PhpProfiler\Lib\Process\MemoryReader\MemoryReaderException;
23
use RuntimeException;
24
25
/**
26
 * Class PhpGlobalsFinder
27
 * @package PhpProfiler\ProcessReader
28
 */
29
final class PhpGlobalsFinder
30
{
31
    private ?int $tsrm_ls_cache = null;
32
    private bool $tsrm_ls_cache_not_found = false;
33
    private BinaryReader $binary_reader;
34
    private PhpSymbolReaderCreator $php_symbol_reader_creator;
35
    /** @var ProcessSymbolReaderInterface[] */
36
    private array $php_symbol_reader_cache = [];
37
38
    /**
39
     * PhpGlobalsFinder constructor.
40
     * @param PhpSymbolReaderCreator $php_symbol_reader_creator
41
     * @param BinaryReader $binary_reader
42
     */
43
    public function __construct(
44
        PhpSymbolReaderCreator $php_symbol_reader_creator,
45
        BinaryReader $binary_reader
46
    ) {
47
        $this->php_symbol_reader_creator = $php_symbol_reader_creator;
48
        $this->binary_reader = $binary_reader;
49
    }
50
51
    /**
52
     * @param int $pid
53
     * @return int
54
     * @throws ElfParserException
55
     * @throws MemoryReaderException
56
     * @throws ProcessSymbolReaderException
57
     * @throws TlsFinderException
58
     */
59
    public function findTsrmLsCache(int $pid): ?int
60
    {
61
        if (!isset($this->tsrm_ls_cache) and !$this->tsrm_ls_cache_not_found) {
62
            $tsrm_lm_cache_cdata = $this->getSymbolReader($pid)->read('_tsrm_ls_cache');
63
            if (isset($tsrm_lm_cache_cdata)) {
64
                $this->tsrm_ls_cache = $this->binary_reader->read64(
65
                    new CDataByteReader($tsrm_lm_cache_cdata),
66
                    0
67
                )->toInt();
68
            } else {
69
                $this->tsrm_ls_cache_not_found = true;
70
            }
71
        }
72
        return $this->tsrm_ls_cache;
73
    }
74
75
    /**
76
     * @param int $pid
77
     * @return ProcessSymbolReaderInterface
78
     * @throws ProcessSymbolReaderException
79
     * @throws ElfParserException
80
     * @throws TlsFinderException
81
     * @throws MemoryReaderException
82
     */
83
    public function getSymbolReader(int $pid): ProcessSymbolReaderInterface
84
    {
85
        if (!isset($this->php_symbol_reader_cache[$pid])) {
86
            $this->php_symbol_reader_cache[$pid] = $this->php_symbol_reader_creator->create($pid);
87
        }
88
        return $this->php_symbol_reader_cache[$pid];
89
    }
90
91
    /**
92
     * @param int $pid
93
     * @return int
94
     * @throws ElfParserException
95
     * @throws MemoryReaderException
96
     * @throws ProcessSymbolReaderException
97
     * @throws TlsFinderException
98
     */
99
    public function findExecutorGlobals(int $pid): int
100
    {
101
        $tsrm_ls_cache = $this->findTsrmLsCache($pid);
102
        if (isset($tsrm_ls_cache)) {
103
            $executor_globals_offset_cdata = $this->getSymbolReader($pid)->read('executor_globals_offset');
104
            if (is_null($executor_globals_offset_cdata)) {
105
                throw new RuntimeException('executor_globals_offset not found');
106
            }
107
            $executor_globals_offset = $this->binary_reader->read64(
108
                new CDataByteReader($executor_globals_offset_cdata),
109
                0
110
            )->toInt();
111
            return $tsrm_ls_cache + $executor_globals_offset;
112
        }
113
        $executor_globals_address = $this->getSymbolReader($pid)->resolveAddress('executor_globals');
114
        if (is_null($executor_globals_address)) {
115
            throw new RuntimeException('executor globals not found');
116
        }
117
        return $executor_globals_address;
118
    }
119
}
120