Skip to content

Commit

Permalink
Merge 3b3457e into 769e482
Browse files Browse the repository at this point in the history
  • Loading branch information
sj-i committed Feb 2, 2022
2 parents 769e482 + 3b3457e commit b882e42
Show file tree
Hide file tree
Showing 31 changed files with 1,103 additions and 23 deletions.
7 changes: 7 additions & 0 deletions src/Command/Inspector/GetCurrentFunctionNameCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use PhpProfiler\Lib\Elf\Process\ProcessSymbolReaderException;
use PhpProfiler\Lib\Elf\Tls\TlsFinderException;
use PhpProfiler\Lib\PhpProcessReader\PhpGlobalsFinder;
use PhpProfiler\Lib\PhpProcessReader\PhpVersionDetector;
use PhpProfiler\Lib\Process\MemoryReader\MemoryReaderException;
use PhpProfiler\Lib\PhpProcessReader\PhpMemoryReader\CallTraceReader;
use Symfony\Component\Console\Command\Command;
Expand All @@ -34,6 +35,7 @@ final class GetCurrentFunctionNameCommand extends Command
{
public function __construct(
private PhpGlobalsFinder $php_globals_finder,
private PhpVersionDetector $php_version_detector,
private CallTraceReader $executor_globals_reader,
private TraceLoopProvider $loop_provider,
private TargetPhpSettingsFromConsoleInput $target_php_settings_from_console_input,
Expand Down Expand Up @@ -70,6 +72,11 @@ public function execute(InputInterface $input, OutputInterface $output): int

$process_specifier = $this->target_process_resolver->resolve($target_process_settings);

$target_php_settings = $this->php_version_detector->decidePhpVersion(
$process_specifier,
$target_php_settings
);

// see the comment at GetTraceCommand::execute()
$eg_address = $this->retrying_loop_provider->do(
try: fn () => $this->php_globals_finder->findExecutorGlobals(
Expand Down
7 changes: 7 additions & 0 deletions src/Command/Inspector/GetTraceCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use PhpProfiler\Lib\Elf\Process\ProcessSymbolReaderException;
use PhpProfiler\Lib\Elf\Tls\TlsFinderException;
use PhpProfiler\Lib\PhpProcessReader\PhpGlobalsFinder;
use PhpProfiler\Lib\PhpProcessReader\PhpVersionDetector;
use PhpProfiler\Lib\Process\MemoryReader\MemoryReaderException;
use PhpProfiler\Lib\PhpProcessReader\PhpMemoryReader\CallTraceReader;
use PhpProfiler\Lib\Process\ProcessStopper\ProcessStopper;
Expand All @@ -40,6 +41,7 @@ final class GetTraceCommand extends Command
{
public function __construct(
private PhpGlobalsFinder $php_globals_finder,
private PhpVersionDetector $php_version_detector,
private CallTraceReader $executor_globals_reader,
private TraceLoopProvider $loop_provider,
private GetTraceSettingsFromConsoleInput $get_trace_settings_from_console_input,
Expand Down Expand Up @@ -85,6 +87,11 @@ public function execute(InputInterface $input, OutputInterface $output): int

$process_specifier = $this->target_process_resolver->resolve($target_process_settings);

$target_php_settings = $this->php_version_detector->decidePhpVersion(
$process_specifier,
$target_php_settings
);

// On targeting ZTS, it's possible that libpthread.so of the target process isn't yet loaded
// at this point. In that case the TLS block can't be located, then the address of EG can't
// be found also. So simply retrying the whole process of finding EG here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
use PhpProfiler\Inspector\Settings\GetTraceSettings\GetTraceSettings;
use PhpProfiler\Inspector\Settings\TargetPhpSettings\TargetPhpSettings;
use PhpProfiler\Inspector\Settings\TraceLoopSettings\TraceLoopSettings;
use PhpProfiler\Lib\PhpInternals\ZendTypeReader;

final class SetSettingsMessage
{
/** @param TargetPhpSettings<value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS>|'auto'> $target_php_settings */
public function __construct(
public TargetPhpSettings $target_php_settings,
public TraceLoopSettings $trace_loop_settings,
Expand Down
9 changes: 8 additions & 1 deletion src/Inspector/Daemon/Reader/Worker/PhpReaderEntryPoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
use PhpProfiler\Inspector\Daemon\Reader\Protocol\PhpReaderWorkerProtocolInterface;
use PhpProfiler\Lib\Amphp\WorkerEntryPointInterface;
use PhpProfiler\Lib\Log\Log;
use PhpProfiler\Lib\PhpProcessReader\PhpVersionDetector;
use PhpProfiler\Lib\Process\ProcessSpecifier;

final class PhpReaderEntryPoint implements WorkerEntryPointInterface
{
public function __construct(
private PhpReaderTraceLoopInterface $trace_loop,
private PhpReaderWorkerProtocolInterface $protocol,
private PhpVersionDetector $php_version_detector,
) {
}

Expand All @@ -50,11 +52,16 @@ public function run(): \Generator
$attach_message->pid
);

$target_php_settings = $this->php_version_detector->decidePhpVersion(
$process_specifier,
$set_settings_message->target_php_settings
);

try {
$loop_runner = $this->trace_loop->run(
$process_specifier,
$set_settings_message->trace_loop_settings,
$set_settings_message->target_php_settings,
$target_php_settings,
$set_settings_message->get_trace_settings
);
Log::debug('start trace');
Expand Down
3 changes: 3 additions & 0 deletions src/Inspector/Daemon/Reader/Worker/PhpReaderTraceLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use PhpProfiler\Inspector\Settings\GetTraceSettings\GetTraceSettings;
use PhpProfiler\Inspector\Settings\TargetPhpSettings\TargetPhpSettings;
use PhpProfiler\Inspector\Settings\TraceLoopSettings\TraceLoopSettings;
use PhpProfiler\Lib\PhpInternals\ZendTypeReader;
use PhpProfiler\Lib\PhpProcessReader\PhpGlobalsFinder;
use PhpProfiler\Lib\PhpProcessReader\PhpMemoryReader\CallTraceReader;
use PhpProfiler\Lib\Process\ProcessSpecifier;
Expand All @@ -37,6 +38,7 @@ public function __construct(
}

/**
* @param TargetPhpSettings<value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS>> $target_php_settings
* @return Generator<TraceMessage>
* @throws \PhpProfiler\Lib\Elf\Parser\ElfParserException
* @throws \PhpProfiler\Lib\Elf\Process\ProcessSymbolReaderException
Expand All @@ -51,6 +53,7 @@ public function run(
): Generator {
$eg_address = $this->php_globals_finder->findExecutorGlobals($process_specifier, $target_php_settings);

/** @var TargetPhpSettings<value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS>> $target_php_settings */
$loop = $this->reader_loop_provider->getMainLoop(
function () use (
$get_trace_settings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
use PhpProfiler\Inspector\Settings\GetTraceSettings\GetTraceSettings;
use PhpProfiler\Inspector\Settings\TargetPhpSettings\TargetPhpSettings;
use PhpProfiler\Inspector\Settings\TraceLoopSettings\TraceLoopSettings;
use PhpProfiler\Lib\PhpInternals\ZendTypeReader;
use PhpProfiler\Lib\Process\ProcessSpecifier;

interface PhpReaderTraceLoopInterface
{
/** @return Generator<TraceMessage> */
/**
* @param TargetPhpSettings<value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS>> $target_php_settings
* @return Generator<TraceMessage>
*/
public function run(
ProcessSpecifier $process_specifier,
TraceLoopSettings $loop_settings,
Expand Down
12 changes: 7 additions & 5 deletions src/Inspector/Settings/TargetPhpSettings/TargetPhpSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@

use PhpProfiler\Lib\PhpInternals\ZendTypeReader;

/**
* @template TVersion of value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS>|'auto'
* @immutable
*/
final class TargetPhpSettings
{
public const PHP_REGEX_DEFAULT = '.*/(php(74|7.4|80|8.0)?|php-fpm|libphp[78]?.*\.so)$';
public const PHP_REGEX_DEFAULT = '.*/(php(74|7.4|80|8.0|81|8.1)?|php-fpm|libphp[78]?.*\.so)$';
public const LIBPTHREAD_REGEX_DEFAULT = '.*/libpthread.*\.so';
public const TARGET_PHP_VERSION_DEFAULT = ZendTypeReader::V80;
public const TARGET_PHP_VERSION_DEFAULT = 'auto';

/** @param value-of<ZendTypeReader::ALL_SUPPORTED_VERSIONS> $php_version */
/** @param TVersion $php_version */
public function __construct(
public string $php_regex = self::PHP_REGEX_DEFAULT,
public string $libpthread_regex = self::LIBPTHREAD_REGEX_DEFAULT,
public string $php_version = self::TARGET_PHP_VERSION_DEFAULT,
public ?string $php_path = null,
public ?string $libpthread_path = null
) {
$this->php_regex = '{' . $php_regex . '}';
$this->libpthread_regex = '{' . $libpthread_regex . '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function createSettings(InputInterface $input): TargetPhpSettings
}

$php_version = $input->getOption('php-version') ?? TargetPhpSettings::TARGET_PHP_VERSION_DEFAULT;
if (!in_array($php_version, ZendTypeReader::ALL_SUPPORTED_VERSIONS, true)) {
if ($php_version !== 'auto' and !in_array($php_version, ZendTypeReader::ALL_SUPPORTED_VERSIONS, true)) {
throw TargetPhpSettingsException::create(
TargetPhpSettingsException::TARGET_PHP_VERSION_INVALID
);
Expand Down
3 changes: 2 additions & 1 deletion src/Lib/Elf/Structure/Elf64/Elf64GnuHashTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ public function __construct(
public function lookup(string $name, callable $symbol_table_checker): int
{
$hash = self::hash($name);
/* this filter is buggy, so commenting out for now
if (!$this->checkBloomFilter($hash)) {
return Elf64SymbolTable::STN_UNDEF;
}

*/
$chain_offset = max(0, $this->buckets[$hash % $this->nbuckets] - $this->symoffset);

do {
Expand Down
29 changes: 29 additions & 0 deletions src/Lib/FFI/Cast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* This file is part of the sj-i/php-profiler package.
*
* (c) sji <sji@sj-i.dev>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace PhpProfiler\Lib\FFI;

use FFI\CData;
use FFI\CInteger;
use FFI\CPointer;

class Cast
{
/** @param CPointer $cdata */
public static function castPointerToInt(CData &$cdata): int
{
/** @var CInteger $casted */
$casted = \FFI::cast('long', $cdata);
return $casted->cdata;
}
}
44 changes: 44 additions & 0 deletions src/Lib/PhpInternals/Types/C/RawInt32.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* This file is part of the sj-i/php-profiler package.
*
* (c) sji <sji@sj-i.dev>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace PhpProfiler\Lib\PhpInternals\Types\C;

use FFI\CInteger;
use PhpProfiler\Lib\PhpInternals\CastedCData;
use PhpProfiler\Lib\Process\Pointer\Dereferencable;
use PhpProfiler\Lib\Process\Pointer\Pointer;

final class RawInt32 implements Dereferencable
{
public int $value;

/** @param CastedCData<CInteger> $casted_cdata */
public function __construct(
private CastedCData $casted_cdata,
) {
$this->value = $this->casted_cdata->casted->cdata;
}

public static function getCTypeName(): string
{
return 'int32_t';
}

public static function fromCastedCData(
CastedCData $casted_cdata,
Pointer $pointer
): static {
/** @var CastedCData<CInteger> $casted_cdata */
return new self($casted_cdata);
}
}
66 changes: 66 additions & 0 deletions src/Lib/PhpInternals/Types/Zend/Bucket.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* This file is part of the sj-i/php-profiler package.
*
* (c) sji <sji@sj-i.dev>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace PhpProfiler\Lib\PhpInternals\Types\Zend;

use FFI\PhpInternals\Bucket as ZendBucket;
use PhpProfiler\Lib\PhpInternals\CastedCData;
use PhpProfiler\Lib\Process\Pointer\Dereferencable;
use PhpProfiler\Lib\Process\Pointer\Pointer;

final class Bucket implements Dereferencable
{
/** @psalm-suppress PropertyNotSetInConstructor */
public Zval $val;
/** @psalm-suppress PropertyNotSetInConstructor */
public int $h;
/**
* @psalm-suppress PropertyNotSetInConstructor
* @var Pointer<ZendString>
*/
public Pointer $key;

/** @param CastedCData<ZendBucket> $casted_cdata */
public function __construct(
private CastedCData $casted_cdata,
) {
unset($this->val);
unset($this->h);
unset($this->key);
}

public function __get(string $field_name): mixed
{
return match ($field_name) {
'val' => $this->val = new Zval($this->casted_cdata->casted->val),
'h' => $this->h = 0xFFFF_FFFF & $this->casted_cdata->casted->h,
'key' => $this->key = Pointer::fromCData(
ZendString::class,
$this->casted_cdata->casted->key
),
};
}

public static function getCTypeName(): string
{
return 'Bucket';
}

public static function fromCastedCData(
CastedCData $casted_cdata,
Pointer $pointer
): static {
/** @var CastedCData<ZendBucket> $casted_cdata */
return new self($casted_cdata);
}
}
Loading

0 comments on commit b882e42

Please sign in to comment.