Ich versuche gerade die Aufrufparameter in einem Windows Kernel Treiber
im IoControlEvent zu analysieren.Dort bekomme unter anderem eine
C-Struktur mit Parametern übergeben von der ich keine Information über
die Struktur und ihre Variablen habe. Ich habe nur die Gesamt-Länge der
Struktur und kenne Variable die sie enthalten muss.
Wenn ich die Variablen so ausgebe ist BusNode und OffsetHigh vertauscht,
OffsetLow stimmt, und nNumberOfBytesToRead = 0.
Frage wie müsste die Struktur mit padding aussehen ?
Ein 3byte padding hätte ich doch nur wenn auf ein UCHAR ein ULONG folgt
oder ?
Das mit dem PAD1 funktioniert leider auch nicht ...
Warum brauche ich PAD2 bis PAD4 da kommt doch nichts mehr das alligned
werden muss ?
Irgendwie drehe ich mich im Kreise
Wenn ich die z.B. die Reihenfolge der Beiden variablen vertausche
> USHORT Bus_Node;> USHORT OffsetHigh;
Werden nicht die Werte getauscht sondern ich bekomme dann auch Müll.
Kennt der Microsoft Compiler (VisulStudio2013) ein flag wo er mir die
Layouts der Datenstrukturen ausgeben kann die er generiert ?
>> Warum brauche ich PAD2 bis PAD4 da kommt doch nichts mehr das alligned> werden muss ?>
Padding is only inserted when a structure member is followed by a member
with a larger alignment requirement or at the end of the structure.
Damit ist die Frage beantwortet
falls du den visualC-Compiler benutzt, kannst du mit -Wall alle
warnungen aktivieren. Dann weist er dich auch auf paddings hin, dann
must du nicht rumraten.
> Kennt der Microsoft Compiler (VisulStudio2013) ein flag wo er mir> die Layouts der Datenstrukturen ausgeben kann die er generiert ?
Keine Ahnung, ob's so ein Flag gibt. Aber wenn du die Felder benutzen
kannst, muß es irgendwo ein include-File geben, wo sie definiert werden.
Hans-Georg L. schrieb:> Das mit dem PAD1 funktioniert leider auch nicht ...
So wird's jedenfalls aufgefüllt, wenn Du nicht gerade mit packed structs
arbeitest. Andernfalls würde der nächste ULONG (nNumberOfBytesToRead)
nicht an eine durch 4 teilbare Adresse gelangen.
> Warum brauche ich PAD2 bis PAD4 da kommt doch nichts mehr das alligned> werden muss ?
Structs werden am Ende aufgefüllt, damit man daraus z.B. problemlos
Arrays bauen kann und immer noch normale Pointerarithmetik hat. Würden
structs nicht aufgefüllt, dann wäre ja das Alignment beim nächsten
identischen Struct im Speicher nicht mehr gegeben.
Achja, noch ein Puzzlestück dazu: das Gesamt-Alignment eines struct
richtet sich immer nach dem der größten Komponente. Da dieses struct
ULONG enthält, wird die Startadresse des structs immer auf eine durch 4
teilbare Adresse gelegt werden.
Die übergebene Struktur ist Bestandteil eines Programmes von dem ich nur
ausfühbare Dateien habe und keine Header oder sonst etwas. Ich versuche
mir eine Struktur zu zusammen zu fummeln die passt.
Was ich noch vergessen habe, die Struktur hat insgesammt 24Byte.
Nop schrieb:> Achja, noch ein Puzzlestück dazu: das Gesamt-Alignment eines struct> richtet sich immer nach dem der größten Komponente. Da dieses struct> ULONG enthält, wird die Startadresse des structs immer auf eine durch 4> teilbare Adresse gelegt werden.
Das würde aber auch nicht zu dem hexdump passen.
Hans-Georg L. schrieb:> Das würde aber auch nicht zu dem hexdump passen.
Zum Hexdump kann alles passen, weil keine Datendefinition dabeisteht.
Abgesehen davon können außerdem auch noch packed structs vorliegen, weiß
man nicht.
Hintergrund ist, ich habe einen WDF Kernel Filter Treiber der die
Kommunikation mit einem Gerät das am Firewirebus hängt belauschen soll.
Siehe: Beitrag "R&S TSMU Radio Network Analyzer"
Da werden im Moment 8 verschiedene control codes verschickt und jeder
hat seine eigene Struktur.
Das sind userdefined structures die kennt Windows nicht.
Abe ich habe etwas gefunden das Macro offsetof kann den offset von
Struktur Variablen ausgeben. Da wird das puzzeln etwas einfacher und ich
kann es im user mode ohne lange turn-around Zeiten testen.
Der erste Test ergibt:
1
typedef struct _ASYNC_READ {
2
USHORT Bus_Node;
3
USHORT OffsetHigh;
4
ULONG OffsetLow;
5
ULONG x1;
6
ULONG nNumberOfBytesToRead;
7
ULONG x2;
8
UCHAR x3;
9
} ASYNC_READ, *PASYNC_READ;
10
11
o_Bus_Node 0x00000000 int
12
o_OffsetHigh 0x00000002 int
13
o_OffsetLow 0x00000004 int
14
o_x1 0x00000008 int
15
o_nNumberOfBytesToRead 0x0000000c int
16
o_x2 0x00000010 int
17
o_x3 0x00000014 int
18
19
size 0x00000018 int
Die 2 USHORT passen in einen ULONG
und es werden nur 3Byte am Ende aufgefüllt.
Manchmal muss man nur eine Nacht darüber schlafen ...
Ich habe heute Morgen nochmal die Bytes hin und her geschubst und mit
anderen Parametern aufgerufen und nichts passt. Nochmal Google
angeworfen und siehe da Firewire arbeitet mit BigEndian dann passt es
auch. Jetzt kann es natürlich noch sein das es innerhalb der Struktur
auch noch gemixt ist.
Naja einfach kann ja jeder ;-)
Hans-Georg L. schrieb:> Abe ich habe etwas gefunden das Macro offsetof kann den offset von> Struktur Variablen ausgeben
Wenn Du offsetof anwenden kannst dann liegen doch die Quellen vor! Dann
schau doch einfach wie es deklariert ist! Oder benutz es einfach so wie
es ist!
Bernd K. schrieb:> Wenn Du offsetof anwenden kannst dann liegen doch die Quellen vor!
Ja, aber nur seine eignen, wo er das mit verschiedenen Strukturvarianten
durchprobiert und dank offsetof nicht manuell mit padding herumrechnen
muß.
Nop schrieb:> dank offsetof nicht manuell mit padding herumrechnen> muß.
Was muss an da groß rechnen? Alle Variablen sind self-aligned, d.h. ihr
Offset ist durch ihre eigene Größe teilbar. Die Padding-Regeln sind also
so simpel dass man Fehl-Alignment schon direkt mit zusammengekniffenen
Augen sehen kann ohne zu rechnen wenn man sich gedanklich ein 2er, 4er
und 8er Raster darunter legt.
Ich mach mir bei sowas als Gedächtnisstütze immer alle 8 Byte eine
Leerzeile ins struct (oder eine Kommentarzeile als Trenner zwischen 8er
Blöcken) und dann muss ich immer nur bis bis maximal 8 zählen (oder
zweimal 4 oder viermal 2) um sofort zu sehen wo der Member überhaupt nur
hinpassen kann bzw. wo vor diesem ein padding entstehen würde. Und da wo
Padding entstehen würde schreib ich dann explizite dummy-Bytes hin damit
meine 8er Blöcke alle voll sind.
So zum Beispiel:
1
typedefstruct{
2
// empty line every 8 bytes to help visualize alignment
3
4
u32magic;
5
u16scale_factor;
6
u16sample_time;
7
8
u64manufacture_date;
9
10
u16pid_kp;
11
u16pid_ki;
12
u16pid_kd;
13
u16pot_threshold_scale;
14
15
u16pot_light_dark_on_scale;
16
u16teach_threshold;
17
out_type_tout_type;// PNP, NPN, etc
18
out_mode_tout_mode;// switching or IO-Link
19
u16pulse_ext_millisec;// pulse extension time
20
21
light_dark_on_mode_tlight_dark_on_mode;// persisted state of pot hysteresis
Nop schrieb:> Bernd K. schrieb:>>> Wenn Du offsetof anwenden kannst dann liegen doch die Quellen vor!>> Ja, aber nur seine eignen, wo er das mit verschiedenen Strukturvarianten> durchprobiert und dank offsetof nicht manuell mit padding herumrechnen> muß.
Ich definiere mir eine Struktur von der ich annehme das sie mit der
unbekannten übereinstimmt und darauf kann ich offseof anwenden.
So sieht meine Struktur jetzt aus und es passt