Belirli bir işlemin 32 veya 64 Bit olup olmadığını belirleme


14

2.6.x veya daha yeni bir Linux çekirdeği ve hem ELF32 hem de ELF64 ikili dosyalarını çalıştırabilen mevcut kullanıcı alanı verildiğinde (yani geçmişim CPU'mun Linux altında 64 bit işletim sistemlerini desteklediğini nasıl bilebilirim ? ) Belirli bir işlemin ( by PID) 32 veya 64 bit modunda mı çalışıyor?

Saf çözüm çalıştırmak olacaktır:

file -L /proc/pid/exe | grep -o 'ELF ..-bit [LM]SB'

ancak bu bilgiler /procgüvenilmeden doğrudan açıklanıyor libmagicmu?

Yanıtlar:


21

Eğer ELF tespiti için kendinizi sınırlamak isterseniz, okuyabilir ELF başlığını arasında /proc/$PID/exekendine. Oldukça önemsiz: dosyadaki 5. bayt 1 ise, 32 bitlik bir ikili dosyadır. 2 ise 64 bittir. Ek sağlık kontrolü için:

  1. İlk 5 bayt ise 0x7f, "ELF", 1: 32 bit ELF ikili dosyasıdır.
  2. İlk 5 bayt ise 0x7f, "ELF", 2: 64 bit ELF ikilidir.
  3. Aksi takdirde: sonuç vermez.

Ayrıca kullanabilirsiniz objdump, ancak bu libmagicbağımlılığınızı ortadan kaldırır ve bir tanesiyle değiştirir libelf.

Başka bir yol : /proc/$PID/auxvdosyayı ayrıştırabilirsiniz . Göre proc(5):

Bu, işlem sırasında işleme geçirilen ELF yorumlayıcı bilgilerinin içeriğini içerir. Biçim bir imzasız uzun kimlik artı her giriş için bir imzasız uzun değerdir. Son giriş iki sıfır içerir.

unsigned longAnahtarların anlamları içeride /usr/include/linux/auxvec.h. Sen istiyorsun AT_PLATFORMki, 0x00000f. Bu konuda bana alıntı yapma, ancak char *platformun dize açıklamasını almak için değerin a olarak yorumlanması gerektiği anlaşılıyor .

Bu StackOverflow sorusunu yararlı bulabilirsiniz .

Yine başka bir yol : Dinamik linker'e ( man ld) yürütülebilir dosya hakkında bilgi dökümü talimatı verebilirsiniz . Çözülmüş AUXV yapısını standart çıktıya yazdırır. Uyarı: Bu bir hack, ama işe yarıyor.

LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1

Bu şöyle bir şey gösterecektir:

AT_PLATFORM:     x86_64

Ben 32-bit ikili bir denedim ve i686yerine aldım .

Bu nasıl çalışır: LD_SHOW_AUXV=1çalıştırılabilir dosyayı çalıştırmadan önce Dinamik Bağlayıcı'ya kodu çözülmüş AUXV yapısını dökmesini bildirir. Eğer sürece gerçekten hayatınızı ilginç yapmak ister, aslında kaçınmak istiyorum çalışıyor yürütülebilir söyledi. Aslında main()işlevini çağırmadan yüklemenin ve dinamik olarak bağlamanın bir yolu ldd(1)üzerinde çalıştırmaktır . Dezavantajı: LD_SHOW_AUXVkabuk tarafından etkinleştirilir, böylece AUXV yapılarının dökümlerini alırsınız: alt kabuk lddve hedef ikili. Biz grepAT_PLATFORM için, ama sadece son satırı tutuyoruz.

Ayrıştırma yardımcısı : Eğer auxvyapıyı kendiniz ayrıştırırsanız (dinamik yükleyiciye güvenmiyorsanız ), o zaman biraz bir muamma vardır: auxvyapı açıkladığı sürecin kuralını takip eder, bu yüzden sizeof(unsigned long)32 bit işlemler için 4 ve 64 için 8 olacaktır bit süreçleri. Bu işi bizim için yapabiliriz. Bunun 32 bit sistemlerde çalışabilmesi için tüm anahtar kodlarının 0xffffffffveya daha azının olması gerekir . 64 bit sistemde, en önemli 32 bit sıfır olacaktır. Intel makineleri küçük endianlardır, bu nedenle bu 32 bit bellekteki en az önemli olanları takip eder.

Bu nedenle, tek yapmanız gereken:

1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3.     Then it's a 64-bit process.
4.     Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6.     Then it's a 32-bit process.
7.     Done.
8. Go to 1.

Maps dosyasını ayrıştırma : Gilles tarafından önerildi, ancak işe yaramadı. İşte değiştirilmiş bir sürümü. /proc/$PID/mapsDosyayı okumaya dayanır . Dosya 64 bit adresleri listeliyorsa, işlem 64 bittir. Aksi takdirde, 32 bittir. Sorun, çekirdeğin, 4'lü gruplar halinde onaltılık adreslerden önde gelen sıfırları sıyırarak çıktıyı basitleştireceği, böylece uzunluk kesmek oldukça işe yaramayacağıdır. awkkurtarmak için:

if ! [ -e /proc/$pid/maps ]; then
    echo "No such process"
else
    case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
    *-) echo "32 bit process";;
    *[0-9A-Fa-f]) echo "64 bit process";;
    *) echo "Insufficient permissions.";;
    esac
 fi

Bu işlemin son hafıza haritasının başlangıç ​​adresini kontrol ederek çalışır. Onlar gibi listelenir 12345678-deadbeef. İşlem 32 bit ise, bu adres sekiz onaltılık basamak uzunluğunda olacak ve dokuzuncu da kısa çizgi olacaktır. 64 bit bir adresse, en yüksek adres bundan daha uzun olacaktır. Dokuzuncu karakter onaltılık bir rakam olacaktır.

Dikkat edin: auxvdosya daha önce bulunmadığından , ilk ve son yöntemler hariç tümü Linux çekirdeği 2.6.0 veya daha yenisine ihtiyaç duyar .


1
Hmmm, ELF üstbilgisinde olup olmadığını merak ediyorum /proc/[pid]/auxv: "ELF yorumlayıcı bilgileri işlem sırasında işleme geçirilir. Biçim bir işaretsiz uzun kimlik artı her giriş için bir işaretsiz uzun değerdir" ( man proc).
goldilocks

1
Başlığın kendisi değil. Sadece hdbir tane edindim ve sihirli numaradan yoksundu. Orada ilgili bazı bilgiler olabilir, ancak bence bu bilgi ELF başlığının kendisinden daha sık değişikliklere tabi olacaktır. Ayrıca 2.6.0'da tanıtıldı, bu yüzden her yerde olduğu gibi değil /proc/PID/exe. Ama yaptığı mimari bilgilere sahibiz. Cevabımı güncelleyeceğim.
Alexios

auxv umduğumdan daha zor olduğu ortaya çıktı - sizeof(unsigned long)64 bit üzerinde 8 veya 32 bit üzerinde 4, yani doğru bir şekilde yorumlamak için sürecin 64 bit mi yoksa 32 bit mi olduğunu bilmek zorundasınız!
Flekso

Kesinlikle haklısın. Bu oldukça can sıkıcı. Hızlı sezgisel tarama: 16x + y (4≤y≤7) baytlarının tümü dosyada sıfırsa, 64 bit yürütülebilir dosyaya bakıyorsunuz demektir. Bu bir çamur: Ben küçük bir endian makinesi varsayıyorum ve tüm auxvanahtar kodları 32 bit sığdırıyor unsigned long, bu yüzden 64 bitlik bir kutudaki en önemli 32 bit sıfır olacaktır.
Alexios

6

Bakın /proc/$pid/maps. Adres aralıkları 32 bit adreslerden (8 onaltılık basamak) veya 64 bit adreslerden (16 onaltılık basamak) fazladır. Bu, hangi formatta olursa olsun, her tür yürütülebilir dosya için geçerlidir. Yalnızca aynı kullanıcı olarak çalışan işlemler hakkında bilgi alabilirsiniz (root değilseniz).

if ! [ -e /proc/$pid/maps ]; then
  echo No such process
elif grep -q '^........[^-]' /proc/$pid/maps; then
  echo 64-bit
elif grep -q . /proc/$pid/maps; then
  echo 32-bit
else
  echo Insufficient permissions
fi

Bu dosyaya erişim izniniz yoksa, tek yolun yürütülebilir dosyayı analiz etmeye çalışmak olduğunu düşünüyorum. (Her zaman okuyabilseniz de /proc/$pid/stat, farklı kullanıcılar olarak çalışan işlemler için gösterilen alanların hiçbiri işlemin bit boyutunu göstermez.) Sürecin çalıştırılabilirliği ile ilgili tahmin yapabilir ps -o comm=ve bunu PATH- içinde görebilirsiniz. farklı bir sürümle başlatılmış PATHolabilir veya yeniden yazmış olabilir argv[0]. Daha sonra yürütülebilir dosyayı analiz edebilirsiniz - ELF'yi kabul etmek istiyorsanız , 5. bayta bakın .


Tarifini test ettim ve başarısız oldu. OpenSuSE 12.2, x86-64, çekirdek 3.4.63-2.44-varsayılan, / bin / bash. İkili ve ilk yığın için / proc / $ pid / maps satırları 32-bit stilinde yazılır, ancak diğerlerinin tümü 64-bit stilindedir. Muhtemelen "% 08x" kullanılarak yazdırılırlar, ancak yine de bu tarif ayarlanacaktır.
Net

Denediğim tüm kutularda 8, 12 ve 16-nybble değerlerinin bir karışımını alıyorum. Kaynağı kontrol etmeden, tahminim çekirdek, dolguyu yazdırılan her satır için adres aralığından daha büyük 16 bitlik en alt katına ayarlar, bu yüzden en uzun onaltılık karakter dizisini bulmanız gerekir, sonra kontrol edin.
Alexios

Çünkü AMA, vsyscallharita her zaman en yüksek olduğu, sadece değişen birlikte kaçmak headiçin tail- ki, ne yazık ki, proc çalışmalarını uygulamıyor çünkü seek(2)bu sanki bir şey daha çirkin olmak zorundasınız, bu yüzdenawk /proc/self/maps -- 'END { print substr($1, 0, 9); }'
Alexios

@Netch Gerçekten, aptalca vsyscall ve yığın satırlarına baktı ve çalıştırılabilir eşleme dikkat etmedi. Teşekkürler, herhangi bir 32-bit olmayan satır aramak için güncelledim. Yazık, bu daha çirkin, ama bu en güvenilir (en azından x86'da kesin ateş, sparc ve arm gibi diğer çift mimarileri kontrol etmedim).
Gilles 'SO- kötü olmayı bırak'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.