Question

I have a chunk of memory populated by external code which I'm trying to reverse engineer. I don't know the complete structure of this memory, but I do know a few fields (e.g. the chunk starts off with an int32 named 'foo' and there's a double at offset 0xC called 'bar'). I want to define a structure and essentially reinterpret-cast a pointer to this memory chunk to that structure, and have it line up. I'm not sure if there's a more conventional name for this technique but I'll refer to it as creating an 'overlay type'.

Here's a sketch of what I'd like to be able to do:

START_OVERLAY_TYPE(my_type, 0xFF) // struct named my_type, size 0xFF
    FIELD(0x00, int32_t foo);     // field int32_t foo at 0x00
    FIELD(0x0C, double bar);      // field double bar at 0x0C
END_OVERLAY_TYPE

Not having to use macros would be a plus, but I don't see a good way around them.

With my current implementation, I expand this to (something like):

__pragma(pack(push, 1))
template<size_t p> struct padding_t { unsigned char pad[p]; };
template<> struct padding_t<0> {};
struct my_type
{
    union
    {
        struct : padding_t<0xFF> {}; // ensure total size is 0xFF
        struct : padding_t<0x00> { int32_t foo; }; // field at 0x00
        struct : padding_t<0x0C> { double bar; }; // field at 0x0C
    };
};
__pragma(pack(pop))

This compiles and works great, at least in the versions I tried of clang, gcc, and VC++ (with appropriate changes to the pragma). Unfortunately, warnings abound due to the non-standard use of anonymous structs.

Is there any way to achieve the same effect while staying within the standard? The requirements are that it be reasonably simple to declare (like the current macro is), and that to the consumer, the usage is indistinguishable from

struct my_type { int32_t foo; double bar; }

at least to the casual observer.

The current code will work for my purposes, I'm just curious if there is a better approach I am overlooking.

Was it helpful?

Solution

You could try something like this with implicit type conversions and assignment operators for the internal struct containing the value. This way instead of using unnamed structs the struct bears the name, but the internals become the unnamed part through operator overloading.

I tried this out with some client code (passing to functions, getting/setting values) and everything seemed fine. It's of course possible that I missed a scenario somewhere.

__pragma(pack(push, 1))
template<size_t p, typename t>
struct padding_t
{
    unsigned char pad[p];
    t             val;
    operator t  () const {return val;}
    operator t& ()       {return val;}
    padding_t<p, t>& operator= (const t& rhs) {val = rhs; return *this;}
};
template<typename t> struct padding_t<0, t>
{
    t             val;
    operator t  () const {return val;}
    operator t& ()       {return val;}
    padding_t<0, t>& operator= (const t& rhs) {val = rhs; return *this;}
};
template<size_t p>
struct sizing_t
{
    unsigned char pad[p];
};
struct my_type
{
    union
    {
        sizing_t<0xFF>           size; // ensure total size is 0xFF
        padding_t<0x00, int32_t> foo;  // field at 0x00
        padding_t<0x0C, double>  bar;  // field at 0x0C
    };
};
__pragma(pack(pop))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top