AddressSanitizer (ASan), bir kullanıcının konumunu algılamaya yönelik hızlı derleyici tabanlı bir araçtır. bellek hatalarını gidermeye çalışır.
ASan şunları algılar:
- Yığın ve yığın tamponu taşması/yetersizliği
- Ücretsiz kullanımdan sonra yığın kullanımı
- Kapsam dışında yığın kullanımı
- Çift serbest/wild serbest
ASan, hem 32 bit hem de 64 bit ARM ile x86 ve x86-64'te çalışır. ASan'ın ek CPU yükü yaklaşık 2 kattır, kod boyutu ek yükü% 50 ila 2 kattır ve ek bellek yükü de fazladır. (ayırma kalıplarınıza bağlıdır, ancak 2x sırasına bağlıdır).
Android 10 ve AArch64'teki AOSP ana dalı, daha düşük RAM yükü ve daha geniş bir tespit edilen hata yelpazesine sahip benzer bir araç olan Donanım Destekli AddressSanitizer (HWASan)'ı destekler. HWASan, dönüşden sonra yığın kullanımını ve ayrıca tespit etti.
HWASan, benzer CPU ve kod boyutu ek yüküne sahiptir ancak çok daha az ek RAM yüküne sahiptir (%15). HWASan yöntemi deterministik değildir. Yalnızca 256 olası etiket değeri vardır. Bu nedenle, herhangi bir hatayı kaçırma ihtimali %0,4'tür. HWASan, taşmayı algılamak için ASan'ın sınırlı boyutlu kırmızı bölgelerine ve serbest bırakıldıktan sonra kullanmayı algılamak için sınırlı kapasiteli karantinaya sahip değildir. Bu nedenle, taşmanın ne kadar büyük olduğu veya belleğin ne kadar süre önce tahsis edildiği HWASan için önemli değildir. Bu sayede HWASan, ASan'dan daha iyidir. Web sitemiz g.co/newsinitiative/labs üzerinden tasarım: HWASan veya Android'de HWASan kullanımı hakkında bilgi edinebilirsiniz.
ASan, yığın taşmalarına ek olarak yığın/küresel taşmaları da algılar ve minimum bellek yükü ile hızlıdır.
Bu dokümanda, Android'in tüm parçalarının/tüm parçalarının nasıl oluşturulacağı ve çalıştırılacağı San. ASan ile bir SDK/NDK uygulaması oluşturuyorsanız Adres Temizleyici .
Bağımsız yürütülebilir dosyaları ASan ile temizleyin
Yürütülebilir dosyanın derleme kuralına LOCAL_SANITIZE:=address
veya sanitize: { address: true }
ekleyin. Kodda mevcut örnekleri arayabilir veya
hazırlayabiliriz.
Bir hata algılandığında ASan, standart
çıkışını ve logcat
komutunu ayarlar, ardından da işlemi kilitler.
Paylaşılan kitaplıkları ASan ile temizleyin
ASan'ın çalışma şekli nedeniyle, ASan ile oluşturulan bir kitaplık yalnızca ASan ile oluşturulan bir yürütülebilir dosya tarafından kullanılabilir.
Birden fazla yürütülebilir dosyada kullanılan (tümü ASan ile derlenmemiş olsa bile) paylaşılan bir kitaplığı temizlemek için kitaplığın iki kopyasına ihtiyacınız vardır. İlgili içeriği oluşturmak için kullanılan
bunu yapmanın önerilen yolu, şunu eklemektir: Android.mk
açıklamanız gerekiyor:
LOCAL_SANITIZE:=address LOCAL_MODULE_RELATIVE_PATH := asan
Bu işlem, kitaplığı şu yerine /system/lib/asan
konumuna getirir:
/system/lib
. Ardından, yürütülebilir dosyanızı şununla çalıştırın:
LD_LIBRARY_PATH=/system/lib/asan
Sistem daemon'ları için /init.rc
veya /init.$device$.rc
'un uygun bölümüne aşağıdakileri ekleyin.
setenv LD_LIBRARY_PATH /system/lib/asan
İşlemin, /proc/$PID/maps
dosyasını okuyarak /system/lib/asan
kitaplıklarını kullandığından emin olun. Aksi halde,
(SELinux'u devre dışı bırakmak için:
adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID # if it is a system service, or may be adb shell stop; adb shell start.
Daha iyi yığın izlemeler
ASan, programdaki her bellek ayırma ve bellek ayırma etkinliği için yığın izleme kaydetmek üzere hızlı, çerçeve işaretçisine dayalı bir çözücü kullanır. En sık çerçeve işaretçileri olmadan tasarlandı. Sonuç olarak, genellikle yalnızca bir veya iki anlamlı kare elde edersiniz. Bu sorunu düzeltmek için kitaplığı ASan ile (önerilir) veya aşağıdakilerle yeniden oluşturun:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
Alternatif olarak işlem sırasında ASAN_OPTIONS=fast_unwind_on_malloc=0
değerini de ayarlayabilirsiniz
bahsedeceğim. İkincisi, yüke bağlı olarak çok fazla CPU kullanabilir.
Sembol
Başlangıçta ASan raporları, ikili programlarda ofsetlere referanslar içerir ve kitaplıklar. Kaynak dosya ve satır bilgilerini iki şekilde edinebilirsiniz:
llvm-symbolizer
ikili dosyası/system/bin
içinde bulunduğundan emin olun.llvm-symbolizer
, şuradaki kaynaklardan geliştirildi:third_party/llvm/tools/llvm-symbolizer
.- Raporu
external/compiler-rt/lib/asan/scripts/symbolize.py
aracılığıyla filtreleyin komut dosyası.
İkinci yaklaşım, ana makinede sembolize edilmiş kitaplıkların bulunması nedeniyle daha fazla veri (yani file:line
konum) sağlayabilir.
Uygulamalarda ASan
ASan, Java kodunu göremez ancak JNI kitaplıklarındaki hataları algılayabilir. Bunun için yürütülebilir dosyayı ASan ile derlemeniz gerekir. Bu durumda /system/bin/app_process(32|64)
kullanılır. Bu
Cihazdaki tüm uygulamalarda ASan'ı aynı anda etkinleştirir.
ancak 2 GB RAM'e sahip bir cihaz bunu yapabilir.
LOCAL_SANITIZE:=address
adlı kişiyi şuraya ekle:
frameworks/base/cmds/app_process
içinde app_process
derleme kuralı Yoksay
Şimdilik aynı dosyada app_process__asan
hedefi (
halen vardır).
Şu öğenin service zygote
bölümünü düzenleyin:
eklemek için uygun system/core/rootdir/init.zygote(32|64).rc
dosyası
sonra, class main
içeren girintili satır blokuna
aynı miktarda girintilendirildi:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
Derleme, adb senkronizasyonu, fastboot flash önyüklemesi ve yeniden başlatma.
wrap mülkünü kullanma
Önceki bölümdeki yaklaşım, ASan'ı sistemdeki her uygulamaya (aslında Zygote sürecinin her alt öğesine) yerleştirir. ASan ile yalnızca bir (veya birkaç) uygulama çalıştırılabilir. Bu durumda, uygulamanın daha yavaş başlatılması için bellek yükü biraz artar.
Bunu, uygulamanızı wrap.
mülküyle başlatarak yapabilirsiniz.
Aşağıdaki örnekte, Gmail uygulaması ASan altında çalıştırılmaktadır:
adb root
adb shell setenforce 0 # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"
Bu bağlamda asanwrapper
, /system/bin/app_process
hücresini yeniden yazar
ve /system/bin/asan/app_process
gibi
San. Ayrıca başına /system/lib/asan
ekler.
dinamik kitaplık arama yolunu izler. Bu sayede, asanwrapper
ile çalıştırıldığında /system/lib/asan
'teki ASan enstrümante edilmiş kitaplıklar, /system/lib
'teki normal kitaplıklara tercih edilir.
Bir hata bulunursa uygulama kilitlenir ve rapor şu adrese yazdırılır: görebilirsiniz.
SANITIZE_HEDEFİ
Android 7.0 ve sonraki sürümler, tüm Android platformunu oluşturma desteğini içerir. Aynı anda birden fazla arama yapabilirsiniz. (Android 9'dan daha yeni bir sürüm oluşturuyorsanız HWASan daha iyi bir seçenektir.)
Aynı derleme ağacında aşağıdaki komutları çalıştırın.
make -j42
SANITIZE_TARGET=address make -j42
Bu modda userdata.img
ek kitaplıklar içerir ve cihaza da yazılmalıdır. Aşağıdaki komut satırını kullanın:
fastboot flash userdata && fastboot flashall
Bu işlem, iki ortak kitaplık grubu oluşturur: /system/lib
içinde normal (ilk make çağrısı) ve /data/asan/lib
içinde ASan enstrümante edilmiş (ikinci make çağrısı). İkinci derlemeden gelen yürütülebilir dosyalar, ilk derlemeden gelenlerin üzerine yazılır. A San Enstrümanlı
yürütülebilir dosyalar aşağıdakileri içeren farklı bir kitaplık arama yolu alır
/system/lib
tarihinden önce /data/asan/lib
kullanarak
PT_INTERP
içinde /system/bin/linker_asan
.
Derleme sistemi, $SANITIZE_TARGET
değeri değiştiğinde ara nesne dizinlerini siler. Bu, /system/lib
altındaki yüklü ikili dosyaları korurken tüm hedeflerin yeniden oluşturulmasını zorunlu kılar.
Bazı hedefler ASan ile oluşturulamaz:
- Statik olarak bağlantılı yürütülebilir dosyalar
LOCAL_CLANG:=false
hedefLOCAL_SANITIZE:=false
,SANITIZE_TARGET=address
için ASan'd değil
Bu tür yürütülebilir dosyalar SANITIZE_TARGET
derlemesinde atlanır ve ilk make çağrısından gelen sürüm /system/bin
içinde bırakılır.
Bu tür kitaplıklar ASan olmadan oluşturulur. Bir miktar ASan içerebilir kodlardan yararlanırız.