C++ Logo

std-proposals

Advanced search

Re: [std-proposals] consteval int relocatability

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Tue, 11 Nov 2025 16:45:38 +0100
An implementation could decide to decrypt the whole memory, not just the vptr. So throwing away data is not an option in that case.   Or at least the part of memory without pod types, e.g. all pointers.   -----Ursprüngliche Nachricht----- Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> Gesendet:Di 11.11.2025 15:34 Betreff:Re: [std-proposals] consteval int relocatability An:std-proposals_at_[hidden]; CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>; On Mon, Nov 10, 2025 at 10:08 AM Oliver Hunt wrote: > > Re: funky - it would actually just be impossible, it is not defined > in a context where C++ exists, and it has no support for the C++ > type system, hence it being invalid to use it over most C++ types. You’re absolutely right about `qsort` using ` void* ` and not having access to the C++ type system – I’d simply overlooked that. I have a question for you Oliver about `std::restart_lifetime` in the presence of arm64e pointer authentication. For the sake of argument, let's suppose that the compiler has a builtin function as follows:    void const * __builtin_get_address_vtable(T); which, for a class type `T`, yields the address of the vtable. Then we could print the vtable address of 'std::ostream' as follows:    #include <iostream>    using namespace std;    int main()    {        cout << __builtin_get_address_vtable(ostream) << endl;    } I had been thinking of `std::restart_lifetime<T>` as “whatever the implementation needs to do so that, after relocation, an object of type `T` behaves as if it had always been at the new address”. On many current ABIs, this would be effectively a no-op, but on arm64e (or on my own new compiler that XOR's the vptr), it clearly has real work to do. In the Kona discussion last Wednesday, it was suggested that an implementation might want an interface roughly like:    template<class T>    T *restart_lifetime(T const *old_p, T *new_p); where `old_p` is the old address of the object and `new_p` is the new address, so the implementation can use both when fixing up vptrs and signatures. What I’m trying to understand though is why the old address has to be exposed in the interface at all? Given the compiler builtin function  `__builtin_get_address_vtable(T)`, it feels like we ought to be able to implement `restart_lifetime` with only the new pointer, by simply discarding the old vptr value and reinitializing it, maybe something like:    template<class T>    T *restart_lifetime(T *const p)    {        void const *vptr = __builtin_get_address_vtable(T);        *reinterpret_cast<void * volatile *>(p) = vptr;        sign_pointer_at_address(p);  // arm64e pointer authentication or similar        return p;    } (Here `sign_pointer_at_address` is pseudocode for whatever pointer authentication primitive the implementation actually uses to sign the vptr based on the address of `*p`.) So my concrete question is: Given an implementation with this kind of ability to obtain the appropriate vtable address for `T`, why is a two-argument interface:        restart_lifetime(T const *old_p, T *new_p) still needed on arm64e? What does `old_p` let you do that you could not, in principle, do by discarding the old vptr and synthesizing a fresh, correctly signed vptr at `new_p`? I’m trying to see the specific arm64e (or similar) scenario that forces the two-argument shape here, rather than a single-argument:    T* restart_lifetime(T *p); that just reconstructs the vptr at the new address. And some people also mentioned scenarios, such as serialisation, where there might not be an old address. -- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-11-11 15:59:19