Passed
Push — master ( bf554b...46a849 )
by Shinji
01:25
created

ProcessModuleSymbolReader::resolveAddressAndSize()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 1
dl 0
loc 17
rs 9.9332
c 0
b 0
f 0
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\Lib\Elf\Process;
15
16
use FFI\CData;
17
use PhpProfiler\Lib\Elf\SymbolResolver\Elf64SymbolResolver;
18
use PhpProfiler\Lib\Process\MemoryMap\ProcessMemoryArea;
19
use PhpProfiler\Lib\Process\MemoryReader\MemoryReaderInterface;
20
use PhpProfiler\Lib\Process\MemoryReader\MemoryReaderException;
21
22
/**
23
 * Class ProcessModuleSymbolReader
24
 * @package PhpProfiler\ProcessReader
25
 */
26
final class ProcessModuleSymbolReader implements ProcessSymbolReaderInterface
27
{
28
    private Elf64SymbolResolver $symbol_resolver;
29
    /** @var ProcessMemoryArea[] */
30
    private array $memory_areas;
31
    private int $base_address;
32
    private MemoryReaderInterface $memory_reader;
33
    private ?int $tls_block_address;
34
    private int $pid;
35
36
    /**
37
     * ProcessModuleSymbolResolver constructor.
38
     * @param int $pid
39
     * @param Elf64SymbolResolver $symbol_resolver
40
     * @param ProcessMemoryArea[] $memory_areas
41
     * @param MemoryReaderInterface $memory_reader
42
     * @param int|null $tls_block_address
43
     */
44
    public function __construct(
45
        int $pid,
46
        Elf64SymbolResolver $symbol_resolver,
47
        array $memory_areas,
48
        MemoryReaderInterface $memory_reader,
49
        ?int $tls_block_address
50
    ) {
51
        $this->pid = $pid;
52
        $this->symbol_resolver = $symbol_resolver;
53
        $this->memory_areas = $memory_areas;
54
        $this->base_address = hexdec(current($memory_areas)->begin);
55
        $this->memory_reader = $memory_reader;
56
        $this->tls_block_address = $tls_block_address;
57
    }
58
59
    /**
60
     * @param string $symbol_name
61
     * @return \FFI\CArray|null
62
     * @throws MemoryReaderException
63
     * @throws ProcessSymbolReaderException
64
     */
65
    public function read(string $symbol_name): ?CData
66
    {
67
        $address_and_size = $this->resolveAddressAndSize($symbol_name);
68
        if ($address_and_size === null) {
69
            return null;
70
        }
71
        [$address, $size] = $address_and_size;
72
        return $this->memory_reader->read($this->pid, $address, $size);
73
    }
74
75
    /**
76
     * @param string $symbol_name
77
     * @return int|null
78
     * @throws ProcessSymbolReaderException
79
     */
80
    public function resolveAddress(string $symbol_name): ?int
81
    {
82
        $address_and_size = $this->resolveAddressAndSize($symbol_name);
83
        if ($address_and_size === null) {
84
            return null;
85
        }
86
        [$address,] = $address_and_size;
87
        return $address;
88
    }
89
90
91
    /**
92
     * @param string $symbol_name
93
     * @return int[]|null
94
     * @throws ProcessSymbolReaderException
95
     */
96
    private function resolveAddressAndSize(string $symbol_name): ?array
97
    {
98
        $symbol = $this->symbol_resolver->resolve($symbol_name);
99
        if ($symbol->isUndefined()) {
100
            return null;
101
        }
102
        $base_address = $this->base_address;
103
104
        if ($symbol->isTls()) {
105
            if (is_null($this->tls_block_address)) {
106
                throw new ProcessSymbolReaderException(
107
                    'trying to resolve TLS symbol but cannot find TLS block address'
108
                );
109
            }
110
            $base_address = $this->tls_block_address;
111
        }
112
        return [$base_address + $symbol->st_value->toInt(), $symbol->st_size->toInt()];
113
    }
114
}
115