Passed
Push — 0.6.x ( 9a1948...a98caa )
by Shinji
03:23 queued 01:32
created

PhpGlobalsFinder::findGlobals()   C

Complexity

Conditions 12
Paths 17

Size

Total Lines 69
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 47
nc 17
nop 3
dl 0
loc 69
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the reliforp/reli-prof 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 Reli\Lib\PhpProcessReader;
15
16
use Reli\Inspector\Settings\TargetPhpSettings\TargetPhpSettings;
17
use Reli\Lib\ByteStream\IntegerByteSequence\IntegerByteSequenceReader;
18
use Reli\Lib\ByteStream\CDataByteReader;
19
use Reli\Lib\Elf\Parser\ElfParserException;
20
use Reli\Lib\Elf\Process\ProcessSymbolReaderException;
21
use Reli\Lib\Elf\Process\ProcessSymbolReaderInterface;
22
use Reli\Lib\Elf\Tls\TlsFinderException;
23
use Reli\Lib\PhpInternals\ZendTypeReader;
24
use Reli\Lib\Process\MemoryReader\MemoryReaderException;
25
use Reli\Lib\Process\MemoryReader\MemoryReaderInterface;
26
use Reli\Lib\Process\ProcessSpecifier;
27
use RuntimeException;
28
29
class PhpGlobalsFinder
30
{
31
    public function __construct(
32
        private PhpSymbolReaderCreator $php_symbol_reader_creator,
33
        private IntegerByteSequenceReader $integer_reader,
34
        private MemoryReaderInterface $memory_reader
35
    ) {
36
    }
37
38
    /**
39
     * @throws MemoryReaderException
40
     * @throws ProcessSymbolReaderException
41
     * @throws TlsFinderException
42
     */
43
    public function findTsrmLsCache(
44
        ProcessSpecifier $process_specifier,
45
        TargetPhpSettings $target_php_settings
46
    ): ?int {
47
        $tsrm_lm_cache_cdata = $this->getSymbolReader(
48
            $process_specifier,
49
            $target_php_settings
50
        )->read('_tsrm_ls_cache');
51
        if (isset($tsrm_lm_cache_cdata)) {
52
            return $this->integer_reader->read64(
53
                new CDataByteReader($tsrm_lm_cache_cdata),
54
                0
55
            )->toInt();
56
        }
57
        return null;
58
    }
59
60
    /**
61
     * @throws MemoryReaderException
62
     * @throws ProcessSymbolReaderException
63
     * @throws TlsFinderException
64
     */
65
    public function getSymbolReader(
66
        ProcessSpecifier $process_specifier,
67
        TargetPhpSettings $target_php_settings
68
    ): ProcessSymbolReaderInterface {
69
        return $this->php_symbol_reader_creator->create(
70
            $process_specifier->pid,
71
            $target_php_settings->php_regex,
72
            $target_php_settings->libpthread_regex,
73
            $target_php_settings->php_path,
74
            $target_php_settings->libpthread_path
75
        );
76
    }
77
78
    /**
79
     * @throws ElfParserException
80
     * @throws MemoryReaderException
81
     * @throws ProcessSymbolReaderException
82
     * @throws TlsFinderException
83
     */
84
    public function findExecutorGlobals(
85
        ProcessSpecifier $process_specifier,
86
        TargetPhpSettings $target_php_settings
87
    ): int {
88
        return $this->findGlobals(
89
            $process_specifier,
90
            $target_php_settings,
91
            'executor_globals'
92
        );
93
    }
94
95
    public function findModuleRegistry(
96
        ProcessSpecifier $process_specifier,
97
        TargetPhpSettings $target_php_settings
98
    ): ?int {
99
        $symbol_reader = $this->getSymbolReader(
100
            $process_specifier,
101
            $target_php_settings
102
        );
103
        $module_registry = $symbol_reader->resolveAddress('module_registry');
104
        return $module_registry;
105
    }
106
107
    public function findGlobals(
108
        ProcessSpecifier $process_specifier,
109
        TargetPhpSettings $target_php_settings,
110
        string $symbol_name,
111
    ): int {
112
        $tsrm_ls_cache = $this->findTsrmLsCache($process_specifier, $target_php_settings);
113
        if (isset($tsrm_ls_cache)) {
114
            switch ($target_php_settings->php_version) {
115
                case ZendTypeReader::V70:
116
                case ZendTypeReader::V71:
117
                case ZendTypeReader::V72:
118
                case ZendTypeReader::V73:
119
                    $id_symbol = $symbol_name . '_id';
120
                    $globals_id_cdata = $this->getSymbolReader($process_specifier, $target_php_settings)
121
                        ->read($id_symbol);
122
                    if (is_null($globals_id_cdata)) {
123
                        throw new RuntimeException('global symbol id not found');
124
                    }
125
                    $tsrm_ls_cache_dereferenced = $this->integer_reader->read64(
126
                        new CDataByteReader(
127
                            $this->memory_reader->read(
128
                                $process_specifier->pid,
129
                                $tsrm_ls_cache,
130
                                8
131
                            )
132
                        ),
133
                        0
134
                    )->toInt();
135
                    $globals_id = $this->integer_reader->read32(
136
                        new CDataByteReader($globals_id_cdata),
137
                        0
138
                    );
139
                    return $this->integer_reader->read64(
140
                        new CDataByteReader(
141
                            $this->memory_reader->read(
142
                                $process_specifier->pid,
143
                                $tsrm_ls_cache_dereferenced + ($globals_id - 1) * 8,
144
                                8
145
                            )
146
                        ),
147
                        0
148
                    )->toInt();
149
150
                case ZendTypeReader::V74:
151
                case ZendTypeReader::V80:
152
                case ZendTypeReader::V81:
153
                    $offset = $symbol_name . '_offset';
154
                    $globals_offset_cdata = $this->getSymbolReader(
155
                        $process_specifier,
156
                        $target_php_settings
157
                    )->read($offset);
158
                    if (is_null($globals_offset_cdata)) {
159
                        throw new RuntimeException('globals offset not found');
160
                    }
161
                    $globals_offset = $this->integer_reader->read64(
162
                        new CDataByteReader($globals_offset_cdata),
163
                        0
164
                    )->toInt();
165
                    return $tsrm_ls_cache + $globals_offset;
166
                default:
167
                    throw new \LogicException('this should never happen');
168
            }
169
        }
170
        $globals_address = $this->getSymbolReader($process_specifier, $target_php_settings)
171
            ->resolveAddress($symbol_name);
172
        if (is_null($globals_address)) {
173
            throw new RuntimeException('global symbol not found ' . $symbol_name);
174
        }
175
        return $globals_address;
176
    }
177
178
    public function findSAPIGlobals(
179
        ProcessSpecifier $process_specifier,
180
        TargetPhpSettings $target_php_settings
181
    ): int {
182
        return $this->findGlobals(
183
            $process_specifier,
184
            $target_php_settings,
185
            'sapi_globals'
186
        );
187
    }
188
}
189