An interesting way to find the size of a structure in C

So today I ran into the problem that I needed to know the size of a structure. Well, ordinarily, you might just do something like this,

        printf("sizeof mystruct = %d\n", sizeof(struct mystruct));

and be done with it.

But, in this particular case the code was in a kernel driver, and I knew the size of the structure was incorrect (as there was some some magic macros watching my back. I knew that the consequence of this being wrong was that the kernel would panic because the structure needed to be padded to be a multiple of a certain size because that’s the only way some hardware that uses it likes it. But how much to pad it? To know that, I needed to know its current size, which I currently didn’t know. Adding the equivalent of the above printf and executing it was out of the question if the kernel panic was to be avoided. I could manually calculate the size of the structure, but it wasn’t trivial or obvious how to do so. Doing so would mean laboriously examining lots of headers, counting up fields, etc. Not fun, and error prone.

I could write some little program that included just the right headers and whatnot with all the right compiler flags, but figuring all that out would be pretty time consuming.

Or, I could do what I did, which was to came up with another, simpler, method. I added some code like this into the driver code:

        printk(KERN_WARNING "%d %d %d\n", 
                0x1234abcd, sizeof(struct mystruct), 0xfedc4321);

Note the very obviously made up but recognizable constants.

I compiled the code, but I did not execute it, didn’t load the module, since if I had, it would have panicked the system, which I wanted to avoid. Instead, I just disassembled the resulting object code (with objdump -d) and got something like this:

 1b:   8d 4c 24 04             lea    0x4(%esp),%ecx
  1f:   83 e4 f0                and    $0xfffffff0,%esp
  22:   ff 71 fc                pushl  -0x4(%ecx)
  25:   55                      push   %ebp
  26:   89 e5                   mov    %esp,%ebp
  28:   51                      push   %ecx
  29:   83 ec 24                sub    $0x24,%esp
  2c:   c7 44 24 0c 21 43 dc    movl   $0xfedc4321,0xc(%esp)
  33:   fe 
  34:   c7 44 24 08 70 02 00    movl   $0x270,0x8(%esp)
  3b:   00 
  3c:   c7 44 24 04 cd ab 34    movl   $0x1234abcd,0x4(%esp)
  43:   12 

Now you can see my obvious constants in there (and search for them, as the complete disassembled driver code was a lot bigger than what you see above). So there are 0xfedc4321 and 0x1234abcd, and right between them is 0x270. And that is the size of my structure, 0x270, and found without executing the code, or making any special program, or manually figuring the structure size.

(Note, the above dump is just a similar example from a user space program, not the actual dump from the kernel code.)

There is probably a simpler way to do this (which I’d be interested to find out, so if you know, leave a comment) but this worked, and quickly and easily.

Maybe someone else will find it helpful in case there turns out not to be a better way.

~ by scaryreasoner on July 2, 2009.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: