HWASan raporlarını anlama

HWASan aracı bir bellek hatası algıladığında işlem abort() ile sonlandırılır ve stderr ile logcat'e bir rapor yazdırılır. Android'deki tüm yerel kilitlenmeler gibi HWASan hataları da /data/tombstones altındadır.

Örnek rapor

Normal yerel kilitlenmelere kıyasla HWASan, kilitlenme mesajının üst kısmındaki İptal mesajı alanında ek bilgiler içerir. Aşağıda, yığına dayalı bir kilitlenme örneği verilmiştir. Grupla ilgili hatalar için gruplara özel bölümlerdeki notu inceleyin.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

Bu, AddressSanitizer raporuna benzer. Bunların aksine, HWASan hatalarının neredeyse tamamı etiket uyuşmazlığı hatasıdır. Yani, işaretçi etiketinin ilgili bellek etiketiyle eşleşmediği bir bellek erişimidir. Bu, aşağıdakilerden herhangi biri olabilir:

  • Yığın veya yığınta sınırların dışında erişim
  • Yığınta serbest bırakmadan sonra kullanma hatası
  • Yığınta döndükten sonra kullanma hatası

Bölümler

HWASan raporunun her bir bölümünün açıklaması aşağıda verilmiştir.

Erişim hatası

Aşağıdakiler dahil olmak üzere hatalı bellek erişimi hakkında bilgi içerir:

  • Erişim türü (READ ve WRITE)
  • Erişim boyutu (erişim denemesi yapılan bayt sayısı)
  • Erişimin ileti dizisi numarası
  • İşaretçi ve bellek etiketleri (ileri düzey hata ayıklama için)

Yığın izlemeye erişme

Hatalı bellek erişiminin yığın izlemesi. Simgelemek için Simgeleme bölümüne bakın.

Neden

Kötü erişimin olası nedeni. Birden fazla aday varsa bunlar olasılık azalan sırayla listelenir. Olası nedenle ilgili ayrıntılı bilgilerden önce gelir. HWASan aşağıdaki nedenleri teşhis edebilir:

  • Ücretsiz kullanımdan sonra
  • Döndürme sonrası yığın kullanımı, kapsam sonrası yığın kullanımı veya sınırların dışında olma gibi yığın etiketi uyuşmazlığı
  • Yığın arabelleği taşması
  • Küresel taşma

Bellek bilgileri

HWASan'ın erişilen bellek hakkında bildiği bilgileri açıklar ve hata türüne göre farklılık gösterebilir:

Hata türü Neden Rapor biçimi
Etiket uyuşmazlığı Ücretsiz kullanımdan sonra Şu rapor biçimini kullanın:
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
Yığın arabelleği taşması Bunun bir alt taşma olabileceğini de unutmayın.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
allocated here:
Grup etiketi uyuşmazlığı Yığın raporları, taşma veya eksik aksama ile döndükten sonra kullanma hataları arasında ayrım yapmaz. Ayrıca, hatanın kaynağı olan yığın tahsisini bulmak için çevrimdışı bir sembolleştirme adımı gerekir. Gruptaki raporları anlama başlıklı makaleyi inceleyin.
Geçersiz ücretsiz Ücretsiz kullanımdan sonra Çift serbest bırakma hatası. Bu durum, işlem kapatıldığında gerçekleşirse ODR ihlaline işaret edebilir.
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
Adres açıklanamıyor Ya rastgele bir serbest bırakma (daha önce ayrılmamış bellek) ya da ayrılan bellek HWASan'ın boş arabelleğinden çıkarıldıktan sonra çift serbest bırakma.
0x..., HWAsan gölge belleğidir. Uygulama, HWASan'a ait belleği boşaltmaya çalıştığı için rastgele bir boşaltma işlemi.

Yer tahsis etme yığın izleme

Belleğin tahsisinden kaldırıldığı yığın izleme. Yalnızca ücretsiz kullanımdan sonra veya geçersiz ücretsiz kullanımla ilgili hatalar için gösterilir. Simgelemek için Simgeleme bölümüne bakın.

Ayırma yığın izleme

Belleğin tahsis edildiği yığın izleme. Simgelemek için Simgeleme bölümüne bakın.

Gelişmiş hata ayıklama bilgileri

HWASan raporunda, aşağıdakiler de dahil olmak üzere bazı gelişmiş hata ayıklama bilgileri de yer alır:

  1. İşlemdeki iş parçacıklarının listesi
  2. İşlemdeki iş parçacıklarının listesi
  3. Hata veren belleğin yakınındaki bellek etiketlerinin değeri
  4. Bellek erişimi noktasındaki kaydedici dökümü

Bellek etiketi dökümü

İşaretçi etiketiyle aynı etikete sahip yakın bellek tahsislerini aramak için etiket bellek dökümü'nü kullanabilirsiniz. Bu etiketler, büyük bir ofset içeren, sınırların dışındaki bir erişimi işaret edebilir. Bir etiket 16 bayt belleğe karşılık gelir. İşaretçi etiketi, adresin en üstteki 8 bitini ifade eder. Etiket bellek dökümü ipucu verebilir. Örneğin, aşağıdaki sağ taraftaki bir arabellek taşmasıdır:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..

İşaretçi etiketiyle eşleşen 6 × 16 = 96 baytlık ad etiketi dizisine dikkat edin.

Bir ayırmanın boyutu 16'nın katı değilse boyutun kalanı bellek etiketi olarak, etiket ise kısa granül etiketi olarak depolanır. Önceki örnekte, kalın harflerle yazılmış ad etiketli ayırmanın hemen ardından 5 × 16 + 4 = 84 baytlık bir 5c etiketi ayırması vardır.

Sıfır bellek etiketi (örneğin, tags: ad/00 (ptr/mem)), döndükten sonra yığın kullanımıyla ilgili bir hatayı gösterir.

Kayıt dökümü

HWASan raporlarındaki kayıt dökümü, geçersiz bellek erişimini gerçekleştiren talimata karşılık gelir. Bu dökümün ardından, normal Android sinyal işleyicisinden alınan başka bir kayıt dökümü gelir. HWASan abort() çağrılırken alındığı ve hatayla alakalı olmadığı için ikinci döküm dosyasını yoksayın.

Simgeleştirme

Yığın izlemelerinde işlev adlarını ve satır numaralarını almak (ve kapsamdan sonra kullanma hatalarıyla ilgili değişken adlarını almak) için çevrimdışı bir sembolleştirme adımı gerekir.

İlk kurulum: llvm-symbolizer'ı yükleyin

Bu simge, sisteminizin llvm-symbolizer yüklü ve $PATH'ten erişilebilir olması gerektiği anlamına gelir. Debian'da sudo apt install llvm kullanarak yükleyebilirsiniz.

Simge dosyalarını edinme

Semboller için, sembol içeren ve sarmalayıcısı kaldırılmış ikili dosyalar gerekir. Bu dosyaların konumu derleme türüne bağlıdır:

  • Yerel derlemeler için simge dosyaları out/target/product/<product>/symbols/ içindedir.
  • AOSP derlemeleri (ör. Android Flash Aracı ile yüklenen) Android CI'de bulunur. Derleme için Öğeler bölümünde bir ${PRODUCT}-symbols-${BUILDID}.zip dosyası vardır.
  • Kuruluşunuzun dahili derlemeleri için simge dosyalarını edinme konusunda yardım almak üzere kuruluşunuzun dokümanlarını inceleyin.

Simgeleştirme

hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

Grup raporlarını anlama

Yığın değişkenleriyle ilgili hatalar için HWASan raporunda aşağıdaki gibi ayrıntılar yer alır:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]

HWASan, yığın hatalarını anlamanıza yardımcı olmak için geçmiş yığın çerçevelerini izler. HWASan, bunları hata raporunda kullanıcıların anlayabileceği bir içeriğe dönüştürmez ve ek bir sembolleştirme adımı gerektirir.

ODR ihlalleri

HWASan tarafından bildirilen bazı ücretsiz kullanım sonrası hatalar, Tek Tanım Kuralı'nın (ODR) ihlal edildiğini gösterebilir. Aynı değişken aynı programda birden çok kez tanımlandığında ODR ihlali meydana gelir. Bu durum, değişkenin birden fazla kez imha edildiği anlamına da gelir. Bu da, serbest bırakıldıktan sonra kullanma hatasına neden olabilir.

Simgeleştirmeden sonra ODR ihlalleri, hem geçersiz erişim yığınında hem de buradan serbest bırakıldı yığınında __cxa_finalize ile ilgili bir serbest bırakıldıktan sonra kullanma hatası gösterir. Daha önce burada ayrılmış yığın __dl__ZN6soinfo17call_constructorsEv içerir ve programınızdaki yığının üst kısmında değişkeni tanımlayan konumu işaret etmelidir.

Statik kitaplıklar kullanılırsa ODR ihlal edilebilir. C++ genel tanımını yapan statik bir kitaplık birden fazla paylaşılan kitaplığa veya yürütülebilir dosyaya bağlanırsa aynı adres alanında aynı sembolün birden fazla tanımı olabilir. Bu da ODR hatasına neden olur.

Sorun giderme

Bu bölümde bazı hatalar ve bunların nasıl ele alınacağı açıklanmaktadır.

HWAddressSanitizer, adresi daha ayrıntılı şekilde açıklayamıyor

Bazen HWASan'da geçmiş bellek tahsisleriyle ilgili bilgiler için yer kalmayabilir. Bu durumda rapor, anlık bellek erişimi için yalnızca bir yığın izleme ve ardından bir not içerir:

HWAddressSanitizer can not describe address in more detail.

Bazı durumlarda, testi birden çok kez çalıştırarak bu sorunu çözebilirsiniz. Başka bir seçenek de HWASan geçmişi boyutunu artırmaktır. Bunu build/soong/cc/sanitize.go'te (hwasanGlobalOptions'u arayın) veya işlem ortamınızda (mevcut ayarları görmek için adb shell echo $HWASAN_OPTIONS'yi deneyin) global olarak yapabilirsiniz.

Bu hata, erişilen bellek eşlenmemişse veya HWASan farkında olmayan bir ayırıcı tarafından ayrılmışsa da ortaya çıkabilir. Bu durumda, kilitlenme üstbilgisinde listelenen mem etiketi genellikle 00 olur. Tam mezar taşı erişiminiz varsa adresin hangi eşlemeye (varsa) ait olduğunu öğrenmek için bellek haritaları dökümüne bakmanız faydalı olabilir.

Aynı ileti dizisinde iç içe yerleştirilmiş hata

Bu, HWASan kilitlenme raporu oluşturulurken bir hata olduğu anlamına gelir. Bu durum genellikle HWASan çalışma zamanındaki bir hatadan kaynaklanır. Hata kaydı gönderin ve mümkünse sorunun nasıl yeniden oluşturulacağına dair talimatlar sağlayın.