Reputation: 191
I have a x86_64
machine, and it can run IA32
process because I have installed a 32bits library. Now I want to know what's the platform that a running process is using? 64bits or 32bits?
The only way I can access the process is a ptrace
system call; I don't have executable file (like I can just execute the file but I don't have read and write permissions), so I can't get the ELF header.
The OS I'm using is Ubuntu 14.04 LTS.
I don't want to get executable file, and then analyse the ELF format. The ONLY WAY I can access the process is ptrace
, or other system calls same as ptrace
if you know, please tell me. Because I want to analyse the process in a C program.
Upvotes: 0
Views: 330
Reputation: 364000
This was also asked on https://unix.stackexchange.com/questions/106234/determine-if-a-specific-process-is-32-or-64-bit, with limited success / viability for detection methods other than checking ELF headers after getting to them in various ways.
Looking at /proc/<pid>/maps
for 64-bit addresses looks viable. So does checking the bitness of /proc/<pid>/exe
:
$ file - < /proc/$(pidof a.out)/exe
/dev/stdin: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=ff6b5084918be4e4daf7e4315fa4d6dd6a039ae7, for GNU/Linux 4.4.0, with debug_info, not stripped
(Or file -L
to follow symlinks. If you just use file /.../exe
, it tells you symbolic link to /tmp/a.out
.)
Note that files in /proc
track the actual inode, so replacing /tmp/a.out
with a different executable does not throw this off. Opening it for reading will open the actual executable that this process has mapped, separate from the name it would report via a readlink()
system call. If that inode has no directory entries anymore, file will report symbolic link to /tmp/a.out (deleted)
, but opening for reading will still get the contents. And renaming a.out
will get the kernel to report the new name as the symlink, like /tmp/bar
.
This answer previously suggested looking at /proc/<pid>/personality
, but the difference I was seeing was that a 32-bit process had the READ_IMPLIES_EXEC
bit set. That's likely because I built a 32-bit executable from asm sources I had been playing with at the time, without the .note.GNU-stack,"",@progbits
that overrides the default of executable stacks, previously implemented by making all pages executable: Unexpected exec permission from mmap when assembly files included in the project
A 32-bit executable compiled by gcc -m32
has personality 00000000
, same as 64-bit /bin/sleep
. So this isn't a useful detection mechanism, unfortunately. I was hoping that 32-bit processes would have some bits set like ADDR_LIMIT_32BIT
, but apparently that's implicit for a 32-bit process, perhaps as part of the "execution domain" like PER_LINUX32
.
I got 00400000
(just READ_IMPLIES_EXEC
) for a 32-bit process with executable stacks (and everything else). (And 00440000
when I had it stopped in a debugger.) The proc(5)
man page says it tells you the personality as set by personality(2)
.
Kernel source for personality bit-numbers: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/personality.h
glibc's copy: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sys/personality.h;hb=HEAD
Mostly leaving this part of the answer here in case the part about decoding personalities is useful to future readers. It's not relevant to finding the bitness of a running process.
Upvotes: 1