PhpGlobalsFinder::findGlobals()   C
last analyzed

Complexity

Conditions 14
Paths 21

Size

Total Lines 71
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 14
eloc 49
nc 21
nop 3
dl 0
loc 71
rs 6.2666
c 1
b 0
f 1

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_ls_cache_cdata = $this->getSymbolReader(
48
            $process_specifier,
49
            $target_php_settings
50
        )->read('_tsrm_ls_cache');
51
        if (isset($tsrm_ls_cache_cdata)) {
52
            return $this->integer_reader->read64(
53
                new CDataByteReader($tsrm_ls_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
    /**
96
     * @throws ElfParserException
97
     * @throws MemoryReaderException
98
     * @throws ProcessSymbolReaderException
99
     * @throws TlsFinderException
100
     */
101
    public function findCompilerGlobals(
102
        ProcessSpecifier $process_specifier,
103
        TargetPhpSettings $target_php_settings
104
    ): int {
105
        return $this->findGlobals(
106
            $process_specifier,
107
            $target_php_settings,
108
            'compiler_globals'
109
        );
110
    }
111
112
    public function findModuleRegistry(
113
        ProcessSpecifier $process_specifier,
114
        TargetPhpSettings $target_php_settings
115
    ): ?int {
116
        $symbol_reader = $this->getSymbolReader(
117
            $process_specifier,
118
            $target_php_settings
119
        );
120
        $module_registry = $symbol_reader->resolveAddress('module_registry');
121
        return $module_registry;
122
    }
123
124
    public function findGlobals(
125
        ProcessSpecifier $process_specifier,
126
        TargetPhpSettings $target_php_settings,
127
        string $symbol_name,
128
    ): int {
129
        $tsrm_ls_cache = $this->findTsrmLsCache($process_specifier, $target_php_settings);
130
        if (isset($tsrm_ls_cache)) {
131
            switch ($target_php_settings->php_version) {
132
                case ZendTypeReader::V70:
133
                case ZendTypeReader::V71:
134
                case ZendTypeReader::V72:
135
                case ZendTypeReader::V73:
136
                    $id_symbol = $symbol_name . '_id';
137
                    $globals_id_cdata = $this->getSymbolReader($process_specifier, $target_php_settings)
138
                        ->read($id_symbol);
139
                    if (is_null($globals_id_cdata)) {
140
                        throw new RuntimeException('global symbol id not found');
141
                    }
142
                    $tsrm_ls_cache_dereferenced = $this->integer_reader->read64(
143
                        new CDataByteReader(
144
                            $this->memory_reader->read(
145
                                $process_specifier->pid,
146
                                $tsrm_ls_cache,
147
                                8
148
                            )
149
                        ),
150
                        0
151
                    )->toInt();
152
                    $globals_id = $this->integer_reader->read32(
153
                        new CDataByteReader($globals_id_cdata),
154
                        0
155
                    );
156
                    return $this->integer_reader->read64(
157
                        new CDataByteReader(
158
                            $this->memory_reader->read(
159
                                $process_specifier->pid,
160
                                $tsrm_ls_cache_dereferenced + ($globals_id - 1) * 8,
161
                                8
162
                            )
163
                        ),
164
                        0
165
                    )->toInt();
166
167
                case ZendTypeReader::V74:
168
                case ZendTypeReader::V80:
169
                case ZendTypeReader::V81:
170
                case ZendTypeReader::V82:
171
                case ZendTypeReader::V83:
172
                    $offset = $symbol_name . '_offset';
173
                    $globals_offset_cdata = $this->getSymbolReader(
174
                        $process_specifier,
175
                        $target_php_settings
176
                    )->read($offset);
177
                    if (is_null($globals_offset_cdata)) {
178
                        throw new RuntimeException('globals offset not found');
179
                    }
180
                    $globals_offset = $this->integer_reader->read64(
181
                        new CDataByteReader($globals_offset_cdata),
182
                        0
183
                    )->toInt();
184
                    return $tsrm_ls_cache + $globals_offset;
185
                default:
186
                    throw new \LogicException('this should never happen');
187
            }
188
        }
189
        $globals_address = $this->getSymbolReader($process_specifier, $target_php_settings)
190
            ->resolveAddress($symbol_name);
191
        if (is_null($globals_address)) {
192
            throw new RuntimeException('global symbol not found ' . $symbol_name);
193
        }
194
        return $globals_address;
195
    }
196
197
    public function findSAPIGlobals(
198
        ProcessSpecifier $process_specifier,
199
        TargetPhpSettings $target_php_settings
200
    ): int {
201
        return $this->findGlobals(
202
            $process_specifier,
203
            $target_php_settings,
204
            'sapi_globals'
205
        );
206
    }
207
}
208