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.