I ran into a problem today with data misalignment. The problem would have taken a lot of time to find if I wasn’t already familiar with the problem (kicking myself now.)
I was porting an existing driver into an old platform to update the platform. So I know that the driver works, but when it started it would data abort. This particular driver is quite large and complex, so a simple read of the code would not be possible in a reasonable amount of time. I have some experience with tracking the cause of a data abort (Windows CE: Finding the cause of a Data Abort.) But this data abort was occurring in Coredll.dll, so I knew that it was because of something that the driver was passing into a function.
Thinking back on what I had done to port the driver into this platform here is what I did:
1.        Copy the driver into the platform
2.       Added some members to a data structure in a header file already in the platform
I know that the driver is well tested, but let’s review the data structure:
#pragma pack(1)
typedef struct _MYSTRUCT {
    BYTE var1;
    BYTE var2;
    DWORD var4;
    BYTE var5;
   DWORD NewVar1;
   DWORD NewVar2;
   DWORD NewVar3;
} MYSTRUCT; 
#pragma pack()
If you look at it closely, you may already have seen my problem. Of course depending on my driver code, this structure could be perfectly acceptable, but knowing my driver it is not. My driver increments NewVar1 using InterlockedIncrement() and decrements it using InterlockedDecrement(). If you aren’t familiar with these functions, these functions take as their parameter a pointer to a 32 bit location. InterlockedIncrment() then effectively does *ptr++ which when I pass in the address of NewVar1 is dereferencing a location that is not 32 bit aligned, which for the ARM processors that I work with causes an exception.
The alignment is not a problem when accessing the structure directly. If I had the following code:
MYSTRUCT *Ptr;
//Allocate some memory for Ptr…
Ptr->NewVar1++;
This would compile and run okay, although some extra assembly code would be generated to handle the alignment for me. The problem also would not exist if the structure wasn’t wrapped with the pragma pack, which tells the compiler not to add any padding to the structure to align the members.
The problem comes from passing the address of NewVar1 into another function.
The solution for my problem is to cause NewVar1 to be aligned by adding an extra byte before it in the definition.
Copyright © 2008 – Bruce Eitman
All Rights Reserved