Consider the following struct on a 64-bit Linux machine:
struct example{unsigned int x;unsigned int * ptr1;unsigned int * ptr2;}
Now the general rule that is followed in alignment of fundamental data types (int, short etc.) is that they are "self-aligned" - which means that a variable gets aligned at a z-byte aligned address where 'z' is the size of the variable. So, a unsigned int variable on a 64-bit machine would get aligned at a 4-byte aligned address (unsigned int is of size 4 bytes on a 64-bit machine that follows LP64 standard - which Linux does) and any pointer at a 8-byte aligned address.
However, it turns out that this pretty intuitive "self-aligned" rule is applicable only for the fundamental data types. For user-defined structs, as in the example above, the rule is a bit different. Instead of the struct getting aligned according to the alignment requirements of its first data member (this is what I expected initially), it gets aligned according to that data-member which has the largest size, and consequently strictest data-alignment requirements. So, the 'struct example' above would start at an 8-byte aligned address (because of the 8-byte pointers), even though its first data member has a looser requirement of a 4-byte aligned address.
Things like these become extremely important when you are unlucky enough to be reading a raw dump of kernel memory with just a struct definition in hand. Even the slightest of mistakes like this as outlined here, can throw all your analysis out of the window.
References:
2. Also, see this for a nice table showing the sizes of fundamental data types on 32 bit and 64 bit machines following various standards (including LP64 - the one followed by Linux).
No comments:
Post a Comment