From 9cc472e68cd507c3425dacdd90b865ad014de563 Mon Sep 17 00:00:00 2001 From: sji Date: Mon, 13 Nov 2023 05:31:23 +0900 Subject: [PATCH] add getPointer() to Dereferencable Some internal structures like zend_object or zend_string uses C struct hack heavily. And the implementation of the memory profiler often needs to know the remote address and it's size of structures. So it's convenient if we can always get the original remote address and size used to dereference the objects. --- src/Lib/PhpInternals/Types/C/RawDouble.php | 8 +++++- src/Lib/PhpInternals/Types/C/RawInt32.php | 8 +++++- src/Lib/PhpInternals/Types/C/RawString.php | 8 +++++- .../Types/Php/SapiGlobalsStruct.php | 8 +++++- src/Lib/PhpInternals/Types/Zend/Bucket.php | 21 +++++++++++++--- src/Lib/PhpInternals/Types/Zend/ZendArray.php | 23 +++++++++++++---- .../Types/Zend/ZendClassEntry.php | 18 ++++++++++--- .../Types/Zend/ZendExecuteData.php | 19 +++++++++++--- .../Types/Zend/ZendExecutorGlobals.php | 19 +++++++++++--- .../PhpInternals/Types/Zend/ZendFunction.php | 15 +++++++++-- .../Types/Zend/ZendModuleEntry.php | 18 ++++++++++--- src/Lib/PhpInternals/Types/Zend/ZendOp.php | 18 ++++++++++--- .../PhpInternals/Types/Zend/ZendString.php | 25 +++++++++++-------- src/Lib/Process/Pointer/Dereferencable.php | 2 ++ .../Types/Zend/ZendStringTest.php | 14 +++++++++-- 15 files changed, 182 insertions(+), 42 deletions(-) diff --git a/src/Lib/PhpInternals/Types/C/RawDouble.php b/src/Lib/PhpInternals/Types/C/RawDouble.php index 58c3a0b7..e302f33c 100644 --- a/src/Lib/PhpInternals/Types/C/RawDouble.php +++ b/src/Lib/PhpInternals/Types/C/RawDouble.php @@ -25,6 +25,7 @@ final class RawDouble implements Dereferencable /** @param CastedCData $casted_cdata */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { $this->value = $this->casted_cdata->casted->cdata; } @@ -39,6 +40,11 @@ public static function fromCastedCData( Pointer $pointer ): static { /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/C/RawInt32.php b/src/Lib/PhpInternals/Types/C/RawInt32.php index 9876b53a..0812db63 100644 --- a/src/Lib/PhpInternals/Types/C/RawInt32.php +++ b/src/Lib/PhpInternals/Types/C/RawInt32.php @@ -25,6 +25,7 @@ final class RawInt32 implements Dereferencable /** @param CastedCData $casted_cdata */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { $this->value = $this->casted_cdata->casted->cdata; } @@ -39,6 +40,11 @@ public static function fromCastedCData( Pointer $pointer ): static { /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/C/RawString.php b/src/Lib/PhpInternals/Types/C/RawString.php index 96fbdb2d..3e72b73e 100644 --- a/src/Lib/PhpInternals/Types/C/RawString.php +++ b/src/Lib/PhpInternals/Types/C/RawString.php @@ -27,6 +27,7 @@ final class RawString implements Dereferencable public function __construct( private CastedCData $cdata, private int $len, + private Pointer $pointer, ) { unset($this->value); } @@ -57,6 +58,11 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - return new self($casted_cdata, $pointer->size); + return new self($casted_cdata, $pointer->size, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Php/SapiGlobalsStruct.php b/src/Lib/PhpInternals/Types/Php/SapiGlobalsStruct.php index 89952d36..25f63742 100644 --- a/src/Lib/PhpInternals/Types/Php/SapiGlobalsStruct.php +++ b/src/Lib/PhpInternals/Types/Php/SapiGlobalsStruct.php @@ -26,6 +26,7 @@ final class SapiGlobalsStruct implements Dereferencable /** @param CastedCData $casted_cdata */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->global_request_time); } @@ -45,6 +46,11 @@ public static function getCTypeName(): string public static function fromCastedCData(CastedCData $casted_cdata, Pointer $pointer): static { /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/Bucket.php b/src/Lib/PhpInternals/Types/Zend/Bucket.php index dcb6e2e2..c9e4e97d 100644 --- a/src/Lib/PhpInternals/Types/Zend/Bucket.php +++ b/src/Lib/PhpInternals/Types/Zend/Bucket.php @@ -30,9 +30,13 @@ final class Bucket implements Dereferencable */ public Pointer $key; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData<\FFI\PhpInternals\Bucket> $casted_cdata + * @param Pointer $pointer + */ public function __construct( - private CastedCData $casted_cdata, + protected CastedCData $casted_cdata, + protected Pointer $pointer, ) { unset($this->val); unset($this->h); @@ -60,7 +64,16 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData<\FFI\PhpInternals\Bucket> $casted_cdata + * @var Pointer $pointer + */ + return new static($casted_cdata, $pointer); + } + + /** @return Pointer */ + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/ZendArray.php b/src/Lib/PhpInternals/Types/Zend/ZendArray.php index 1bdcc72d..9fb8aa92 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendArray.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendArray.php @@ -42,7 +42,8 @@ * zend_long nNextFreeElement; * dtor_func_t pDestructor; * }; */ -final class ZendArray implements Dereferencable +/** @psalm-consistent-constructor */ +class ZendArray implements Dereferencable { /** @psalm-suppress PropertyNotSetInConstructor */ public int $flags; @@ -64,9 +65,13 @@ final class ZendArray implements Dereferencable /** @psalm-suppress PropertyNotSetInConstructor */ public int $nNextFreeElement; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer, + */ public function __construct( - private CastedCData $casted_cdata + protected CastedCData $casted_cdata, + protected Pointer $pointer, ) { unset($this->flags); unset($this->nTableMask); @@ -158,7 +163,15 @@ public static function getCTypeName(): string public static function fromCastedCData(CastedCData $casted_cdata, Pointer $pointer): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new static($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/ZendClassEntry.php b/src/Lib/PhpInternals/Types/Zend/ZendClassEntry.php index 86f16852..a1ff8e73 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendClassEntry.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendClassEntry.php @@ -27,9 +27,13 @@ final class ZendClassEntry implements Dereferencable */ public Pointer $name; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->name); } @@ -53,8 +57,16 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } public function getClassName(Dereferencer $dereferencer): string diff --git a/src/Lib/PhpInternals/Types/Zend/ZendExecuteData.php b/src/Lib/PhpInternals/Types/Zend/ZendExecuteData.php index 9da57ea3..11ab0c8d 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendExecuteData.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendExecuteData.php @@ -30,9 +30,13 @@ final class ZendExecuteData implements Dereferencable /** @var Pointer|null */ public ?Pointer $opline; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->func); unset($this->prev_execute_data); @@ -78,8 +82,17 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new self($casted_cdata, $pointer); + } + + /** @return Pointer */ + public function getPointer(): Pointer + { + return $this->pointer; } public function getFunctionName(Dereferencer $dereferencer): ?string diff --git a/src/Lib/PhpInternals/Types/Zend/ZendExecutorGlobals.php b/src/Lib/PhpInternals/Types/Zend/ZendExecutorGlobals.php index cf14147b..b0073c3b 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendExecutorGlobals.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendExecutorGlobals.php @@ -23,9 +23,13 @@ final class ZendExecutorGlobals implements Dereferencable /** @var Pointer|null */ public ?Pointer $current_execute_data; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->current_execute_data); } @@ -52,7 +56,16 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new self($casted_cdata, $pointer); + } + + /** @return Pointer */ + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/ZendFunction.php b/src/Lib/PhpInternals/Types/Zend/ZendFunction.php index 2bbd65e8..11c27432 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendFunction.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendFunction.php @@ -41,9 +41,11 @@ final class ZendFunction implements Dereferencable /** * @param CastedCData $casted_cdata + * @param Pointer $pointer */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->type); unset($this->function_name); @@ -84,8 +86,17 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new static($casted_cdata, $pointer); + } + + /** @return Pointer */ + public function getPointer(): Pointer + { + return $this->pointer; } public function getFullyQualifiedFunctionName(Dereferencer $dereferencer): string diff --git a/src/Lib/PhpInternals/Types/Zend/ZendModuleEntry.php b/src/Lib/PhpInternals/Types/Zend/ZendModuleEntry.php index 76e9ce25..4f7ebc72 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendModuleEntry.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendModuleEntry.php @@ -31,9 +31,13 @@ final class ZendModuleEntry implements Dereferencable */ public Pointer $version; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->zts); unset($this->version); @@ -65,7 +69,15 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/ZendOp.php b/src/Lib/PhpInternals/Types/Zend/ZendOp.php index 2017ae05..98aa823d 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendOp.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendOp.php @@ -39,9 +39,13 @@ final class ZendOp implements Dereferencable /** @psalm-suppress PropertyNotSetInConstructor */ public int $extended_value; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, + private Pointer $pointer, ) { unset($this->op1); unset($this->op2); @@ -79,7 +83,15 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - return new self($casted_cdata); + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ + return new self($casted_cdata, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } } diff --git a/src/Lib/PhpInternals/Types/Zend/ZendString.php b/src/Lib/PhpInternals/Types/Zend/ZendString.php index 1378a5e5..b29fea5b 100644 --- a/src/Lib/PhpInternals/Types/Zend/ZendString.php +++ b/src/Lib/PhpInternals/Types/Zend/ZendString.php @@ -31,10 +31,14 @@ final class ZendString implements Dereferencable */ public Pointer $val; - /** @param CastedCData $casted_cdata */ + /** + * @param CastedCData $casted_cdata + * @param Pointer $pointer + */ public function __construct( private CastedCData $casted_cdata, private int $offset_to_val, + private Pointer $pointer, ) { unset($this->h); unset($this->len); @@ -62,16 +66,17 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static { - /** @var CastedCData $casted_cdata */ - /* - $head_addr = \FFI::cast('long', \FFI::addr($cdata))->cdata; - $val_addr = \FFI::cast('long', \FFI::addr($cdata->val))->cdata; - $offset_to_val = $val_addr - $head_addr; - - return new self($cdata, $offset_to_val); - */ + /** + * @var CastedCData $casted_cdata + * @var Pointer $pointer + */ // an almost safe assumption I think - return new self($casted_cdata, 24); + return new self($casted_cdata, self::ZEND_STRING_HEADER_SIZE, $pointer); + } + + public function getPointer(): Pointer + { + return $this->pointer; } /** diff --git a/src/Lib/Process/Pointer/Dereferencable.php b/src/Lib/Process/Pointer/Dereferencable.php index e8fd461a..abdf2816 100644 --- a/src/Lib/Process/Pointer/Dereferencable.php +++ b/src/Lib/Process/Pointer/Dereferencable.php @@ -29,4 +29,6 @@ public static function fromCastedCData( CastedCData $casted_cdata, Pointer $pointer ): static; + + public function getPointer(): Pointer; } diff --git a/tests/Lib/PhpInternals/Types/Zend/ZendStringTest.php b/tests/Lib/PhpInternals/Types/Zend/ZendStringTest.php index f1556be8..e2915da4 100644 --- a/tests/Lib/PhpInternals/Types/Zend/ZendStringTest.php +++ b/tests/Lib/PhpInternals/Types/Zend/ZendStringTest.php @@ -33,7 +33,12 @@ public function testValues(): void 'val' => $string_addr, ], ), - 24 + 24, + new Pointer( + ZendString::class, + 147, + 255, + ) ); $this->assertSame(123, $zend_string->h); $this->assertSame(234, $zend_string->len); @@ -56,7 +61,12 @@ public function testGetValuePointer(): void 'val' => $string_addr, ], ), - 24 + 24, + new Pointer( + ZendString::class, + 152, + 280, + ) ); $value_pointer = $zend_string->getValuePointer( new Pointer(RawString::class, 123, 16)