What's the best and most reliable way to detect if a 32-bit user mode program is running on a 64-bit kernel or not (i.e. if the system is in 'long mode')? I'd rather not call external programs if possible (or have to load any kernel modules).
Note: I want to detect whether a 64-bit kernel is being used (or really, whether the CPU is in long mode), not simply if a 64-bit capable processor is present (/proc/cpuinfo
tells me that but not whether the 64-bit capability is being used).
The kernel fakes a 32-bit processor if uname
is compiled 32-bit or if setarch i686
is used.
Call the uname()
function and check the returned machine
string, which will be x86_64
for a 64-bit Intel platform.
One way of reversing the effect of the use of setarch
is to reset the personality:
#include <stdio.h>
#include <sys/utsname.h>
#include <sys/personality.h>
int main()
{
struct utsname u;
personality(PER_LINUX);
uname(&u);
puts(u.machine);
return 0;
}
This shows the right results when compiled in 32-bit mode and run on a 64-bit system:
$ gcc -m32 -o u u.c
$ ./u
x86_64
$ setarch i686 ./u
x86_64
EDIT: Fixed code to reverse effect of setarch
.
Reference.
Assuming that uname() is cheating, there are still several mechanisms. One way is to check the width of the address of any of the kernel symbols.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char *inputline = malloc(1024);
char *oinputline = inputline;
int fd = open("/proc/kallsyms", O_RDONLY);
int numnibbles = 0;
if (fd == -1) {
perror("open");
free(inputline);
exit(1);
}
read(fd, inputline, 1024);
close(fd);
while(!isspace(*inputline)) {
numnibbles++;
inputline++;
}
printf("%dbit\n", numnibbles*4);
free(oinputline);
exit (0);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With