2016-06-09 21 views
6

Gibt es eine Möglichkeit zu sehen, wie C-Strukturen während der Erstellung gepackt werden? Ich habe durch mehrere ähnliche Beiträge zu lesen, wie structs verpackt sein:Zeigen Sie, wie C-Strukturen während der Erstellungszeit gepackt werden

Aber ich frage mich, ist es eine Art von Build-Zeit-Datei generiert, die mich genau zeigt, Wie ist eine Struktur gepackt? Ich habe versucht, die Mapping-Datei zu überprüfen, die vom Linker generiert wurde, aber diese Informationen fehlen.

PS: Ich versuche, ein paar Mikrocontroller miteinander über UART zu kommunizieren und weil der eine 16 Bit und der andere 32 Bit ist, treffe ich jedes Mal ein paar Fehler, wenn ich diese Strukturen aktualisiere.

+3

Es gibt ein Makro 'offsetof()' in 'stddef.h'. Siehe https://en.wikipedia.org/wiki/Offsetof – cdarke

+0

Die DWARF-Informationen in jedem Objekt haben das (wenn Debug-Informationen aktiviert sind). Aber es bedarf einiger Analyse, um die Daten zu extrahieren. – kaylum

+1

Sie können sicher die 'pack' Breite für Ihre Struktur festlegen und den gleichen Wert für beide Projekte erzwingen. – LPs

Antwort

1

Der Präprozessor ist nicht in der Lage, Strukturoffsets zu berechnen, so dass keine Menge an Makrozauber allein Ihre Offsets für Sie abgibt.

Wenn Sie für eingebettete Ziele erstellen, können Sie wahrscheinlich .bin-Dateien erstellen (nicht elf, coff, mach-o). Wenn Sie jeden Ihrer Zielcompiler verwenden, um ein Array von Offsets in einer Objektdatei zu erstellen und dann in eine Bin-Datei zu speichern, sollte es möglich sein, die Bin-Dateien für jedes Ihrer Ziele zu vergleichen. Es wäre eine gute Idee, den Prozess für Build-Time-Checks zu automatisieren. Hier

ist ein Beispiel dafür, was ich spreche:

#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) 
}; 

Dies ist nur eine Tabelle von Offsets erzeugt. Erstellen Sie dies für eine Mipsel und x86_64 und vergleichen. Hier ist eine Make-Datei:

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 $< > [email protected] 

hexdump.$(T2).txt: offsets.$(T2).bin 
    hexdump -C $< > [email protected] 

offsets.$(T1).bin: offsets.$(T1).o 
    $(OBJCPY1) -j.data -O binary $< [email protected] 

offsets.$(T2).bin: offsets.$(T2).o 
    $(OBJCPY2) -j .data -O binary $< [email protected] 

offsets.$(T1).o: offsets.c 
    $(CC1) -Wall -c -o [email protected] $< 

offsets.$(T2).o: offsets.c 
    $(CC2) -Wall -c -o [email protected] $< 

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 

nun die Offsets zu vergleichen ist recht einfach:

[email protected] ~/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 
[email protected] ~/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 

Die Mips sendet einen 32-Byte-Datenabschnitt anstelle der x86 20 Byte. Wenn Sie die Größe offsets festlegen, sollten Sie cmp verwenden können, um die beiden in Ihrem Build zu vergleichen.

Wenn Ihre Ziele eine unterschiedliche Endgültigkeit aufweisen, müssen Sie möglicherweise das Makro o so ändern, dass ntohl oder ähnliches verwendet wird, um beide Compiler zum Ausgeben von Ganzzahlen im selben Format zu veranlassen.