flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > Error in 64-bit version of SYSTEM_INFO structure

Author
Thread Post new topic Reply to topic
JPowersFairfax



Joined: 25 Jan 2012
Posts: 11
Location: Virginia
JPowersFairfax 15 Mar 2013, 20:30
The "dwActiveProcessorMask" field in the SYSTEM_INFO structure is actually a DWORD_PTR, not a DWORD (as the Hungarian notation implies). So, in the 64-bit version of the structure (in KERNEL64.INC), it should be a QWORD.

An important side-effect of this error is that the value read from the "dwAllocationGranularity" field will be wrong for 64-bit programs. That's how I found the error.


Last edited by JPowersFairfax on 31 May 2021, 09:30; edited 1 time in total
Post 15 Mar 2013, 20:30
View user's profile Send private message Visit poster's website Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 15 Mar 2013, 22:22
Hmm, are you sure it is dwNumberOfProcessors that is DWORD_PTR? According to MSDN it is dwActiveProcessorMask that is DWORD_PTR:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724958%28v=vs.85%29.aspx

Code:
typedef struct _SYSTEM_INFO {
  union {
    DWORD  dwOemId;
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;
    };
  };
  DWORD     dwPageSize;
  LPVOID    lpMinimumApplicationAddress;
  LPVOID    lpMaximumApplicationAddress;
  DWORD_PTR dwActiveProcessorMask;
  DWORD     dwNumberOfProcessors;
  DWORD     dwProcessorType;
  DWORD     dwAllocationGranularity;
  WORD      wProcessorLevel;
  WORD      wProcessorRevision;
} SYSTEM_INFO;    
Post 15 Mar 2013, 22:22
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 15 Mar 2013, 22:34
comrade,

Fortunately that doesn't change alignof (and sizeof in an unexpected way). DWORD_PTR and dw prefix are really misleading here.
Post 15 Mar 2013, 22:34
View user's profile Send private message Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 16 Mar 2013, 05:06
What about alignof and sizeof?

The prefix is indeed misleading but intentionally stayed the same for source code portability. The structure was extended from its 32-bit counterpart when the Win64 port was made, so field names had to stay the same. Changing the field name would break existing pre-Win64 programs from compiling with the newest SDK.

Anyway, I think JPowersFairfax's point is that somebody should update the equates. That would be Tomasz.
Post 16 Mar 2013, 05:06
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 16 Mar 2013, 08:48
comrade wrote:
What about alignof and sizeof?
Let's see:
Code:
#include <stdio.h>

typedef unsigned char BYTE;
typedef unsigned __int64 QWORD;
typedef struct {
        BYTE Size;
        QWORD Count;
        BYTE Character;
} SAMPLE;

#define offsetof(s,m) (size_t)&(((s *)0)->m)
#define alignof(T) offsetof(struct { char c; T m; }, m)

int main() {
        printf(
                "sizeof SAMPLE = %d\n"
                "alignof SAMPLE = %d\n",
                sizeof(SAMPLE),
                alignof(SAMPLE)
        );
}    
Code:
sizeof SAMPLE = 24
alignof SAMPLE = 8    
As a rule of thumb, alignment of structure is maximum of alignments of its components; size of structure is always a multiple of its alignment (thus array items become aligned too).

Back to the subject, lpMin/MaximumApplicationAddress fields already force proper alignment, and additional 4 bytes for dwActiveProcessorMask in 64-bit structure won't increase its size more than for that 4 bytes (luckily tail has acceptable size: 4+4+4+2+2 = 16).

Platform SDK includes are so intertwined that it's easy to make a mistake. My usual practice is to preprocess corresponding .H with proper #defines and analyze result thoroughly. Additional tests are needed almost every time, due to vague points in C specification (sizeof(long int)? Wink).
Post 16 Mar 2013, 08:48
View user's profile Send private message Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 16 Mar 2013, 09:03
What does all this have to do with OPs concern? Somebody fix KERNEL64.INC, that is all.
Post 16 Mar 2013, 09:03
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 16 Mar 2013, 09:33
comrade,

It means that conversion of C structures to fasm ones isn't an easy walk. Proper alignment of fields and necessary padding aren't obvious and could require quite a research.

Probably it could be automated. I'll try to write awk script that generates C sources to check fasm includes for struct discrepancies (I do expect a lot of them Wink).
Post 16 Mar 2013, 09:33
View user's profile Send private message Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 17 Mar 2013, 04:04
baldr wrote:

It means that conversion of C structures to fasm ones isn't an easy walk. Proper alignment of fields and necessary padding aren't obvious and could require quite a research.


Hmm, good point. Though I thought Windows header all used #pragma pack(1) (1-byte alignment). So all padding and alignment had to be done via explicit structure members.
Post 17 Mar 2013, 04:04
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 17 Mar 2013, 06:01
comrade,

Heh, most 5 (ERROR_ACCESS_DENIED) and 87 (ERROR_INVALID_PARAMETER) failures are due to improper alignment. Since most of NT kernel is written in C, compiler handles that issues under the hood; assembly level programmers have to deal with it raw.
Post 17 Mar 2013, 06:01
View user's profile Send private message Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 17 Mar 2013, 08:36
baldr wrote:

Since most of NT kernel is written in C, compiler handles that issues under the hood; assembly level programmers have to deal with it raw.

They don't just blindly let the compiler decide the alignment. There is always some alignment specified and agreed on, as part of the ABI.

The NT kernel also runs on platforms where misaligned access will cause exceptions (ARM with Windows RT, and IA-64), so they have to be wary of alignment even if it is written in C.
Post 17 Mar 2013, 08:36
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.