Friday, August 2, 2013

container_of and offsetof in C++

I'm just putting this here for future reference

Linux uses a macro called container_of in kernel

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({                      \
      const typeof(((type *)0)->member) * __mptr = (ptr);     \
      (type *)((char *)__mptr - offsetof(type, member)); })

BSD has one

#define CONTAINING_RECORD(addr, type, field)    \
      ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))

and so does windows

#define CONTAINING_RECORD(address, type, field) ((type *)( \
                                              (PCHAR)(address) - \
                                              (ULONG_PTR)(&((type *)0)->field)))

( These were all found at http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi )

I've written the linux version as a C++ template.

template<class P, class M>
size_t offsetof(const M P::*member)
{
    return (size_t) &( reinterpret_cast<P*>(0)->*member);
}

template<class P, class M>
P* container_of(M* ptr, const M P::*member)
{
    return (P*)( (char*)ptr - offsetof(member));
}

This has the added benefit of being able to 'step-into' the function, unlike a macro call.  But this also requires it to be done in C++, and not C.

In C you would call the macro        container_of( pointer, Foo, bar)
In C++ you would call the function container_of( pointer,  &Foo::bar )

Monday, July 15, 2013

Microsoft Visual C memory segments

If you look in a file called Microsoft Visual Studio\VC\crt\src\sect_attribs.h you'll see a list of #pragma's for section attributes.  This is here to define memory segments in your compiled software.   After a little searching on the internet I wasn't able to find a list of what each of this segments were for.  Poking around the rest of the CRT source was able to give me some clues.


#pragma section(".CRTMP$XCA",long,read)
#pragma section(".CRTMP$XCZ",long,read)
#pragma section(".CRTMP$XIA",long,read)
#pragma section(".CRTMP$XIZ",long,read)

#pragma section(".CRTMA$XCA",long,read)
#pragma section(".CRTMA$XCZ",long,read)
#pragma section(".CRTMA$XIA",long,read)
#pragma section(".CRTMA$XIZ",long,read)

#pragma section(".CRTVT$XCA",long,read)
#pragma section(".CRTVT$XCZ",long,read)

These sections are used for initializers of globals when you are building a managed binary.  The $XI are C initializes while the $XC are C++ initializers.   The MP means managed per process, while the MA means managed per app domain.  The VT stands for VTABLE, in other words your virtual method initializers.  I found this all in crt\src\mstartup.cpp.   Something interesting is the C initializers are never called.

#pragma section(".CRT$XCA",long,read)
#pragma section(".CRT$XCC",long,read)
#pragma section(".CRT$XCZ",long,read)
#pragma section(".CRT$XIA",long,read)
#pragma section(".CRT$XIC",long,read)
#pragma section(".CRT$XID",long,read)
#pragma section(".CRT$XIY",long,read)
#pragma section(".CRT$XIZ",long,read)

These sections are used for native initializers. Like before $XI are C while $XC are C++ initializers.  The XCC section is the list of C++ initializers and the XIC are the C initializers.  The XID and XIY seems to be a special sections of C initializers that are to be run after all the C initializers

#pragma section(".CRT$XCAA",long,read)
#pragma section(".CRT$XIAA",long,read)

These sections are for native PRE-initializers.  That is, they are run before the above initializers.

#pragma section(".CRT$XPA",long,read)
#pragma section(".CRT$XPB",long,read)
#pragma section(".CRT$XPX",long,read)
#pragma section(".CRT$XPXA",long,read)
#pragma section(".CRT$XPZ",long,read)
#pragma section(".CRT$XTA",long,read)
#pragma section(".CRT$XTB",long,read)
#pragma section(".CRT$XTX",long,read)
#pragma section(".CRT$XTZ",long,read)

These are C terminators (read destructors), that get called on exit.  $XP are pre-terminators, and $XT are normal terminators.

#pragma section(".CRT$XDA",long,read)
#pragma section(".CRT$XDC",long,read)
#pragma section(".CRT$XDL",long,read)
#pragma section(".CRT$XDU",long,read)
#pragma section(".CRT$XDZ",long,read)

These are used for Thread Local Storage dynamic initializers.  You can find a detailed explanation in crt\src\tlsdyn.c.

#pragma section(".CRT$XLA",long,read)
#pragma section(".CRT$XLC",long,read)
#pragma section(".CRT$XLD",long,read)
#pragma section(".CRT$XLZ",long,read)

These seem to be for bootstrapping for Thread Local Storage.  From a comment in src\crt\tlssup.c
/* Start section for TLS callback array examined by the OS loader code.
 * If dynamic TLS initialization is used, then a pointer to __dyn_tls_init
 * will be placed in .CRT$XLC by inclusion of tlsdyn.obj.  This will cause
 * the .CRT$XD? array of individual TLS variable initialization callbacks
 * to be walked.
 */
If I understand this correctly, it means that if you have Thread Local Storage enabled, a pointer to __dyn_tls_init will be placed in .CRT$XLC, which should cause it to be called and your TLS to be initialized as needed.  The XLD points to _dyn_tls_dtor, which calls the destructors for Thread Local Storage.

For an explanation on what these sections are used for read this blog