C Struktur Puzzle

OP #5565620
Lesenswert?

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.
1
// structur definition aus Beispielen passt nicht   
2
typedef struct _ASYNC_READ_ORG {
3
  ULONG           bRawMode;
4
  ULONG           bGetGeneration;
5
  IO_ADDRESS      DestinationAddress; //BusNr NodeNr Ofset-hi offset-Low
6
  ULONG           nNumberOfBytesToRead;
7
  ULONG           nBlockSize;
8
  ULONG           fulFlags;
9
  ULONG           ulGeneration;
10
  UCHAR           Data[1];
11
} ASYNC_READ_ORG, *PASYNC_READ_ORG;
12

13
// dummy structur für meinen memory dump
14
typedef struct _ASYNC_READ_DBG {
15
  ULONG           w1;
16
  ULONG           w2;
17
  ULONG           w3;
18
  ULONG           w4;
19
  ULONG           w5;
20
  ULONG           w6;
21
} ASYNC_READ_DBG, *PASYNC_READ_DBG;
22

23
// der hexdump (little endian)
24
FFFFCEFF 
25
000400F0 
26
10FBDB02 
27
00000000  
28
00040000
29
00000000 
30
// reihenfolge im speicher (big endian)
31
FFCEFFFF
32
F0000400
33
02DBFB10
34
00000000 
35
00000400
36
00000000
37

38
BYTE Reihenfolgen die Sinn ergeben
39
FFCE      -> BUS_NODE 10bit BusNr=0x3FF + 6Bit NodeNr=0x0E
40
FFFF      -> OffsetHigh
41
F0000400  -> Offset Low  
42
00000400  -> nNumberOfBytesToRead 
43
 
44
// so müsste die Struktur ohne padding aussehen 
45
typedef struct _ASYNC_READ {
46
  USHORT  Bus_Node; 
47
  USHORT  OffsetHigh;
48
  ULONG   OffsetLow;
49
  UCHAR   x1;
50
  UCHAR   x2;
51
  UCHAR   x3;
52
  ULONG   nNumberOfBytesToRead;
53
  ULONG   x4;
54
  UCHAR   x5;
55
} ASYNC_READ, *PASYNC_READ;

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 ?
Gast #5565627
Lesenswert?

Hans-Georg L. schrieb:

> Frage wie müsste die Struktur mit padding aussehen ?
1
typedef struct _ASYNC_READ {
2
  USHORT  Bus_Node;
3
  USHORT  OffsetHigh;
4
  ULONG   OffsetLow;
5
  UCHAR   x1;
6
  UCHAR   x2;
7
  UCHAR   x3;
8
  UCHAR   PAD1;
9
  ULONG   nNumberOfBytesToRead;
10
  ULONG   x4;
11
  UCHAR   x5;
12
  UCHAR   PAD2;
13
  UCHAR   PAD3;
14
  UCHAR   PAD4;
15
} ASYNC_READ, *PASYNC_READ;
OP #5565668
Lesenswert?

Nop schrieb:
> Hans-Georg L. schrieb:
>
>> Frage wie müsste die Struktur mit padding aussehen ?
>
>
1
typedef struct _ASYNC_READ {
2
>   USHORT  Bus_Node;
3
>   USHORT  OffsetHigh;
4
>   ULONG   OffsetLow;
5
>   UCHAR   x1;
6
>   UCHAR   x2;
7
>   UCHAR   x3;
8
>   UCHAR   PAD1;
9
>   ULONG   nNumberOfBytesToRead;
10
>   ULONG   x4;
11
>   UCHAR   x5;
12
>   UCHAR   PAD2;
13
>   UCHAR   PAD3;
14
>   UCHAR   PAD4;
15
> } ASYNC_READ, *PASYNC_READ;

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 ?
OP #5565686
Lesenswert?

Hans-Georg L. schrieb:
> Nop schrieb:
>> Hans-Georg L. schrieb:
>>>
>>> Frage wie müsste die Struktur mit padding aussehen ?
>>
>>
1
typedef struct _ASYNC_READ {
2
>>   USHORT  Bus_Node;
3
>>   USHORT  OffsetHigh;
4
>>   ULONG   OffsetLow;
5
>>   UCHAR   x1;
6
>>   UCHAR   x2;
7
>>   UCHAR   x3;
8
>>   UCHAR   PAD1;
9
>>   ULONG   nNumberOfBytesToRead;
10
>>   ULONG   x4;
11
>>   UCHAR   x5;
12
>>   UCHAR   PAD2;
13
>>   UCHAR   PAD3;
14
>>   UCHAR   PAD4;
15
>> } ASYNC_READ, *PASYNC_READ;
>

> 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
Gast #5565740
Lesenswert?

> 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.
Gast #5565768
Lesenswert?

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.
Gast #5565770
Lesenswert?

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.
OP #5565875
Lesenswert?

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.
OP #5566084
Lesenswert?

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 ;-)
#5566304
Lesenswert?

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
typedef struct {
2
  // empty line every 8 bytes to help visualize alignment
3

4
  u32 magic;
5
  u16 scale_factor;
6
  u16 sample_time;
7

8
  u64 manufacture_date;
9

10
  u16 pid_kp;
11
  u16 pid_ki;
12
  u16 pid_kd;
13
  u16 pot_threshold_scale;
14

15
  u16 pot_light_dark_on_scale;
16
  u16 teach_threshold;
17
  out_type_t out_type;      // PNP, NPN, etc
18
  out_mode_t out_mode;      // switching or IO-Link
19
  u16 pulse_ext_millisec;    // pulse extension time
20

21
  light_dark_on_mode_t light_dark_on_mode;  // persisted state of pot hysteresis
22
} settings_t;
OP #5566384
Lesenswert?

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
1
  typedef struct _ASYNC_READ {
2
    USHORT  Bus_Node;     // BigEndian
3
    USHORT  OffsetHigh;   // BigEndian
4
    ULONG   OffsetLow;    // BigEndian
5
    ULONG   Unknown1;     // ?
6
    ULONG   Unknown2;     // ?
7
    ULONG   nNumberOfBytesToRead; // BigEndian
8
    UCHAR   data[1];      // Data Start
9
  } ASYNC_READ, *PASYNC_READ;

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren