Windows 64-bit and 32-bit incompatibilities - windows

I know that 64-bit applications need 64-bit Windows.
Which c/c++ code will work only for 64-bit or 32-bit exclusively?
Edit: I have found it here
Can I determine proccess word size on runtime: Like I will have 32-bit application which returns if OS is 32 or 64 bit and then runs sub/new proccess with right word size.

You can find out if your system is 32-bit or 64-bit with GetNativeSystemInfo. For example, you could do something like this:
typedef void (WINAPI *GetNativeSystemInfo_t)(LPSYSTEM_INFO lpSystemInfo);
BOOL IsSystem64Bit()
{
HANDLE kernel32 = LoadLibrary("kernel32.dll");
SYSTEM_INFO si;
GetNativeSystemInfo_t GetNativeSystemInfoPtr
= (GetNativeSystemInfo_t)GetProcAddress(kernel32, "GetNativeSystemInfo");
if (GetNativeSystemInfoPtr == NULL)
return FALSE;
GetNativeSystemInfoPtr(&si);
return (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
}
The reason the function is resolved dynamically is because it doesn't exist on versions of Windows prior to XP. (And on those versions of windows, we already know that the system is not 64-bit)

I'm not sure about Windows, and so obviously this will be limited in helpfulness, but on Linux you can determine word size at runtime. A long int will be the word size. On 64-bit Linux long is 64-bits and 32-bits on 32-bit Linux.
So, this seems really stupid and inconsistent, but you could do something like
char ws[3];
sprintf(ws, "%d", sizeof(long));
fprintf(stderr, "%s\n", ws);
You can then compare ws with different values to see what the word size is. I'm sure that Windows has a comparable basic type that can help you tell what the word size is.

Related

Call address using assembly code

In our application, I have the following source code:
#define GET_CALL_ADDRESS(VAR) asm("movl 4(%%ebp),%0;" : "=r"(VAR));
void * _our_malloc(size_t size)
{
unsigned long calladdr;
...
GET_CALL_ADDRESS(calladdr);
...
return p;
}
I would like to know what does GET_CALL_ADDRESS do ? This code compiles and works fine on 32-bit machine.
But on 64-bit machine, during compilation I get the following error:
Error: incorrect register `%rax' used with `l' suffix
The directive
asm("movl 4(%%ebp),%0;" : "=r"(VAR));
copies a 32-bit quantity from [EBP+4] to VAR. VAR in your case is defined as calladdr. This assumes that the return address is 32-bit, which is not true anymore in a 64-bit system, and it assumes that the return address is at [EBP+4], which is also not true anymore in a 64-bit system.
The reason why it fails is that calladdr is something like [EBP-x] (where x is some number like 4,) and there is no single Intel x86 instruction that will both fetch from [EBP+4] and store at [EBP-x], so the value fetched from [EBP+4] must be stored in some register, and then the value of that register must be stored at [EBP-x]. Then for some unknown to me reason gcc decides to use register rax for this job, but rax is 64-bit wide, while the 'l' prefix of the movl instruction implies a 32-bit quantity, so there is a mismatch.
Even if you somehow managed to sort this out, your next problem would be that on a 64-bit architecture, the return address is not at [EBP+4].
So, this entire clause is an assumption that you are in 32-bits.
My recommendation: completely ditch this nonsense and replace it with some ready-made library (no need to re-invent the wheel) that works both in 32-bit and 64-bit mode, or with gcc's built-in function for retrieving the return address, as suggested by Michael Petch; then proceed to rebuild in 64-bit like a boss.

Qt get system 32bit or 64 bit info?

I am writing a software using Qt. One of my task is to judge whether Windows OS is 32bit or 64bit, and then do the following operations according this fact.
However, when I was trying "QSysInfo::WordSize", it always return 32 while I was actually running on Windows 7-64 bit OS.
I also tried
#ifdef _WIN32
return 32;
#elif _WIN64
return 64;
This also returns 32.
Actually Qt is 32bit in my system. Is that the problem?
How can I get the actual word size of Windows?
Thanks
I personally would call GetNativeSystemInfo and check the value of the wProcessorArchitecture field.
The _WIN32 and _WIN64 macros are, like all macros, evaluated at compile time. They tell you about the architecture of your executable file rather than the architecture of the system on which the executable runs. That latter information, the information that you want, can only be determined at runtime.
QSysInfo::WordSize only tells you if the application is compiled on a 32-bit platform or a 64-bit platform. So, yes, in a way being compiled using a 32-bit Qt will return a word size of 32.
For your case, you might want to check IsWow64Process.
This should work in any c++ environment, including Qt's, on any system that doesn't use "segment registers" (IOW, has a properly flat memory space):
uint32_t archwidth = sizeof(int *); // arch width in bytes
uint32_t archbits = 8 * archwidth; // arch width in bits
The mechanism here is:
On a 64-bit architecture (like the XEON) the CPU will use 8 byte (64-bit) pointers, and so archwidth will return 8; and archbits is then 8*8, or 64.
On a 32-bit architecture (like the 68000) the CPU will use 4 byte (32-bit) pointers, and so archwidth will return 4; and archbits is then 4*8, or 32.
On a 16-bit architecture (like the 6809) the CPU will use 2 byte (16-bit) pointers, and so archwidth will return 2; and archbits is then 2*8, or 16.
You can use Q_PROCESSOR_WORDSIZE (or here). I'm surprised it's not documented because it's not in a private header (QtGlobal) and is quite handy.
It could be more preferable for some use cases because it doesn't depend on processor architecture. (e.g. it's defined the same way for x86_64 as well as arm64 and many others)
Example:
#include <QtGlobal>
#include <QDebug>
int main() {
#if Q_PROCESSOR_WORDSIZE == 4
qDebug() << "32-bit executable";
#elif Q_PROCESSOR_WORDSIZE == 8
qDebug() << "64-bit executable";
#else
qDebug() << "Processor with unexpected word size";
#endif
}
or even better:
int main() {
qDebug() << QStringLiteral("%1-bit executable").arg(Q_PROCESSOR_WORDSIZE * 8);
}

Is it possible to read process memory of a 64 bit process from a 32bit app?

On windows 64 bit, I've got a 32 bit process that reads the memory of other 32 bit processes, and I'd like it to be able to read 64 bit processes too.
ReadProcessMemory is being used to read the memory, but it has a 32 bit limitation. Is there any way of doing the equivalent of a ReadProcessMemory on a 64 bit process?
I know I could write a 64 bit process and launch that from my 32 bit process to do the work, but I'm wondering if there's some other option so that I don't need to write a 64 bit process.
Thanks.
It's possible.
For an example you may refer to the excellent sample in the answer of tofucoder.
For one more sample you may refer to this link.
For explanation why it actually works please check this thread.
Another sample may be found here.
The whole trick is to call 64-bit version of ReadProcessMemory function. Intuitively it's not an option from 32-bit process however the link above explains: x64 version of ntdll.dll is also loaded as a part of 32-bit process in Windows WOW64 emulator. It has a function called NtReadVirtualMemory with the same prototype as ReadProcessMemory64:
__declspec(SPEC)BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
The address is 64-bit long and thus the whole virtual address space of 64-bit process may be referred.
You may wonder how to get the address of this function. It's when another function in ntdll.dll comes in handy: LdrGetProcedureAddress. Its prototype is the same as of GetProcAddress:
__declspec(SPEC)DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, char* funcName);
We are to examine export directory of x64 ntdll.dll and manually found this function's entry. Then we can obtain address of any other function.
Another question is left uncovered so far: how to obtain start address of x64 ntdll.dll? We need to manually walk through x64 PEB structure of our process and traverse loaded modules' list - as one of the variants. And how to get PEB address? Please refer to the links above, not to overflow this post with too many details.
All this is covered in sample from the first link.
Alternative variants with usage of NtReadVirtualMemory & NtWow64ReadVirtualMemory64 functions are provided in second & third links (as well as alternative ways to get PEB address).
Summary: it is possible to interact with x64 process from x86 one. It can be done either with direct call to x64 version of function (from x64 ntdll.dll which is loaded as a part of WOW64 process) or with the call of specific x86 function which is intended to work with x64 process (namely NtWow64ReadVirtualMemory64).
P.S. One may say it's undocumented and is more like hack - but it's just not officially documented. Soft like Unlocker, ProcessHacker or ProcessExplorer, for example, makes use of these undocumented features (and many more), and it's up to you to decide, of course.
The library wow64ext seems to have solved this problem and offers a function ReadProcessMemory64 The Visual Studio Extension VSDebugTool seems to use this library and works for me with 64 bit processes.
Anyway, it shouldn't be impossibe because the (32 bit) Visual Studio Debugger handles 64 bit Debuggees very well.
No: http://blogs.msdn.com/b/oldnewthing/archive/2008/10/20/9006720.aspx
There's no way to get around this. One solution is to stop using the WOW64 emulator and write a 64 bit process. Another solution is to use IPC rather than direct memory reading.
ReadProcessMemory can read any size of memory including from x86 processes reading x64 processes.
You can without a problem, in an x86 program, do the following:
DWORD64 test = 0;
ReadProcessMemory(hProcess, (LPCVOID)lpBaseAddress, &test, sizeof(DWORD64), NULL);
Which would allow you to dereference an x64 pointer from a x86 process.

check CPU type at RUN time for C program on MAC

How does a C program determine, at RUN time (not compile time),
whether it's running on Little-Endian or Big-Endian CPU?
The reason why it must be "run-time" check, not "complie-time", is because I'm building the program in MAC OSX's Universal Binary format, using my MAC with Intel-CPU. And this program is expected to run on both Intel and Power-PC CPU's. ie, through the Universal Binary format on MAC, I wanna build a program using Intel-CPU and run it under PPC CPU.
The logic in my program that needs the CPU check is the host-to-network-byte-order-changing function for 64bit integers. Right now I have it blindly swap the byte orders, which works ok on Intel-CPU, but breaks on PPC. Here's the C function:
unsigned long long
hton64b (const unsigned long long h64bits) {
// Low-order 32 bits in front, followed by high-order 32 bits.
return (
(
(unsigned long long)
( htonl((unsigned long) (h64bits & 0xFFFFFFFF)) )
) << 32
)
|
(
htonl((unsigned long) (((h64bits) >> 32) & 0xFFFFFFFF))
);
}; // hton64b()
Any better way of doing this in a cross-platform way?
Thanks
Don't bother checking; just use hton* wherever you need a network-independent value. With a good design, that should be limited to just the module that interfaces between your program and whatever it is that needs network-independent integers.
On big-endian systems that are already in network order, hton* is probably just a macro, so it's free. On little-endian systems, you're going to need to do it anyway, so checking if you need to do it is just slowing you down.
If this is insufficient, then you'll need to provide a better explanation of what you're trying to accomplish and why you need to know the endianness of the system at runtime.
There will be preprocessor macros
available for testing wether it's
big/little endian. e.g.
#ifdef LITTLE_ENDIAN
do it little endian way
#else
do it big endian way
#endif.
This is compile time, but the source for fat
binaries gets compiled seperatly for
each architecture , this is not a
problem.
Im not sure if macosx has the
betoh64() function in sys/endian.h -
if it does - use that it'll do the
right thing.
The last approach is to simply do the
unpacking of the individual bytes in
a way that's not sensible to the host
endian - you only need to know the
order the bytes are in from the
source.
uint64_t unpack64(uint8_t *src)
{
uint64_t val;
val = (uint64_t)src[0] << 56;
val |= (uint64_t)src[1] << 48;
val |= (uint64_t)src[2] << 40;
val |= (uint64_t)src[3] << 32;
val |= (uint64_t)src[4] << 24;
val |= (uint64_t)src[5] << 16;
val |= (uint64_t)src[6] << 8;
val |= (uint64_t)src[7] ;
return val;
}
Do you realize that universal binaries on the mac are compiled multiple times, once for each architecture? I imagine that when you talk about compile time, you're referring to using your configure/make system to notify the source.... Just use gcc constants (like LITTLE_ENDIAN )
You don't need to check the endianness at runtime. When you compile an application as universal binary, it is compiled multiple times with the appropriate defines and macros, EVEN if you are building on an Intel machine. At runtime, the mach-o loader will choose the best architecture to run from your universal binary (i.e. ppc on PowerPC or i386 on Intel).
Universal binary does not mean one binary for multiple architecture. It means one fat binary containing one binary for one architecture.
Please refer to http://developer.apple.com/legacy/mac/library/documentation/MacOSX/Conceptual/universal_binary/universal_binary_intro/universal_binary_intro.html for more details.

DWORD_PTR, INT_PTR, LONG_PTR, UINT_PTR, ULONG_PTR When, How and Why?

I found that Windows has some new Windows Data Types
DWORD_PTR, INT_PTR, LONG_PTR, UINT_PTR, ULONG_PTR
can you tell me when, how and why to use them?
The *_PTR types were added to the Windows API in order to support Win64's 64bit addressing.
Because 32bit APIs typically passed pointers using data types like DWORD, it was necessary to create new types for 64 bit compatibility that could substitute for DWORD in 32bit applications, but were extended to 64bits when used in a 64bit applications.
So, for example, application developers who want to write code that works as 32bit OR 64bit the windows 32bit API SetWindowLong(HWND,int,LONG) was changed to SetWindowLongPtr(HWND,int,LONG_PTR)
In a 32bit build, SetWindowLongPtr is simply a macro that resolves to SetWindowLong, and LONG_PTR is likewise a macro that resolves to LONG.
In a 64bit build on the other hand, SetWindowLongPtr is an API that accepts a 64bit long as its 3rd parameter, and ULONG_PTR is typedef for unsigned __int64.
By using these _PTR types, one codebase can compile for both Win32 and Win64 targets.
When performing pointer arithmetic, these types should also be used in 32bit code that needs to be compatible with 64bit.
so, if you need to access an array with more than 4billion elements, you would need to use an INT_PTR rather than an INT
CHAR* pHuge = new CHAR[0x200000000]; // allocate 8 billion bytes
INT idx;
INT_PTR idx2;
pHuge[idx]; // can only access the 1st 4 billion elements.
pHuge[idx2]; // can access all 64bits of potential array space.
Chris Becke is pretty much correct. Its just worth noting that these _PTR types are just types that are 32-bits wide on a 32-bit app and 64-bits wide on a 64-bit app. Its as simple as that.
You could easily use __int3264 instead of INT_PTR for example.

Resources