Is there any way to see how C structs are packed during build time? I've read through several similar posts about how structs may be packed:
But I'm wondering is there some kind of build time generated file that shows me exactly how a struct is packed? I tried checking the mapping file generated by the linker but it doesn't have this information.
PS: I'm trying to get a few microcontrollers to communicate with each other via UART and because one is 16 bit and the others are 32 bit, I'm hitting a few bugs everytime I update these structs.
The preprocessor won't be able to figure out structure offsets, so no amount of macro magic alone will dump your offsets for you.
If you are building for embedded targets, you will probably be able to create .bin files (not elf, coff, mach-o). If you use each of your target compilers to create an array of offsets in an object file and then dump it to a bin file, it should be possible to compare the bin files for each of your targets. It would be a good idea to automate the process for build time checks.
Here is an example of what I'm talking about:
#include <stdint.h>
#include <stddef.h>
typedef struct s1{
uint16_t f1;
uint32_t f2;
uint64_t f3;
int8_t f4[5];
uint32_t f5[2];
}s1;
#define o(f) ((int32_t)offsetof(s1,f))
int32_t offsets[]={
o(f1),
o(f2),
o(f3),
o(f4),
o(f5)
};
This just creates a table of offsets. Build this for a mipsel and x86_64 and compare. Here is a make file:
T1:=x86_64-linux-gnu
CC1:=$(T1)-gcc
OBJCPY1:=$(T1)-objcopy
T2:=mipsel-linux
CC2:=$(T2)-gcc
OBJCPY2:=$(T2)-objcopy
.PHONY: all cmp clean hexdumps
all: hexdumps
hexdumps: hexdump.$(T1).txt hexdump.$(T2).txt
hexdump.$(T1).txt: offsets.$(T1).bin
hexdump -C $< > $@
hexdump.$(T2).txt: offsets.$(T2).bin
hexdump -C $< > $@
offsets.$(T1).bin: offsets.$(T1).o
$(OBJCPY1) -j.data -O binary $< $@
offsets.$(T2).bin: offsets.$(T2).o
$(OBJCPY2) -j .data -O binary $< $@
offsets.$(T1).o: offsets.c
$(CC1) -Wall -c -o $@ $<
offsets.$(T2).o: offsets.c
$(CC2) -Wall -c -o $@ $<
clean:
-rm -f offsets.$(T1).o offsets.$(T2).o
-rm -f offsets.$(T1).bin offsets.$(T2).bin
-rm -f hexdump.$(T1).txt hexdump.$(T2).txt
Now, comparing the offsets is pretty easy:
evaitl@evbb ~/se $ cat hexdump.mipsel-linux.txt
00000000 00 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 |................|
00000010 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
evaitl@evbb ~/se $ cat hexdump.x86_64-linux-gnu.txt
00000000 00 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 |................|
00000010 18 00 00 00 |....|
00000014
The mips emits a 32 byte data section instead of the x86 20 byte. If you set the size of offsets
, you should be able to use cmp
to compare the two in your build.
If your targets have different endianess, you may need to change the o
macro to use ntohl
or some such to get both compilers to emit integers in the same format.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With