3 puan yazan GN⁺ 2024-06-10 | 2 yorum | WhatsApp'ta paylaş
  • libtree, ldd çıktısını bir ağaca dönüştüren ve paylaşılan kütüphanelerin nasıl bulunduğunu ya da neden bulunamadığını açıklayan bir araçtır
  • Varsayılan çıktıda bazı standart bağımlılıkları gizler; -v, -vv, -vvv ile gizli kütüphaneleri ve daha önce karşılaşılan kütüphanelerin bağımlılıklarını kademeli olarak görebilirsiniz
  • --path veya -p, soname yerine yolu gösterir; --max-depth ile özyinelemeli arama derinliği sınırlandırılabilir
  • Kurulum, v3.1.1 önceden derlenmiş ikili dosyaları, Fedora/RHEL/CentOS, Ubuntu 22.04+ ve GNU Guix üzerinden yapılabilir
  • Kaynaktan derleme için C99 anlayan bir C derleyicisi gerekir; make kullanılırken LDFLAGS=-static önerilir

libtree ne yapar

  • libtree, ldd çıktısını ağaç biçimine dönüştüren bir araçtır
  • Paylaşılan kütüphanelerin nasıl bulunduğunu ya da neden konumlarının tespit edilemediğini açıklar
  • README içinde doc/screenshot.png ekran görüntüsü yer alır

Çıktı seçenekleri

  • Varsayılan çıktıda bazı standart bağımlılıklar gösterilmez
  • Daha ayrıntılı çıktı, verbosity seçenekleriyle kontrol edilir
    • libtree -v: Varsayılan olarak atlanan kütüphaneleri gösterir
    • libtree -vv: Varsayılan olarak atlanan kütüphanelerin bağımlılıklarını da gösterir
    • libtree -vvv: Daha önce karşılaşılan kütüphanelerin bağımlılıklarını da gösterir
  • --path veya -p bayrağı, soname yerine yolu gösterir
    • Örnek: libtree -p $(which tar)
  • --max-depth, özyineleme derinliğini sınırlar

Kurulum yöntemleri

Kaynaktan derleme

  • libtree, C99 anlayan bir C derleyicisi gerektirir
  • Temel derleme adımları, depoyu klonlayıp ardından make çalıştırmaktır
  • make kullanılırken LDFLAGS=-static önerilir
  • README içinde, curl ile libtree.c indirip derlemeye yönelik unsafe quick install komutu da ayrı bir katlanır bölümde sunulur

2 yorum

 
GN⁺ 2024-06-10
Hacker News yorumları
  • Bu araç da ldd’nin, denetlenen kütüphanelerin bir kısmını gerçekten çalıştırıveren beklenmedik davranışını aynen izliyor mu?
    https://catonmat.net/ldd-arbitrary-code-execution

    • Son dönemde, kabaca 5 yıldan daha eski olmayan ldd sürümleri hedef ikiliyi çalıştırmıyor
      Referans: https://manpages.debian.org/unstable/manpages/ldd.1.en.html#...
    • Mobilde koda hızlıca göz attım; öyle yapmıyor gibi görünüyor
      Aslında ELF dosyasını doğrudan ayrıştırıyor ve bağımlılıkları da özyinelemeli olarak ayrıştırıyor gibi; bu oldukça güzel
    • Python için belli belirsiz benzer bir şey yapmıştım ama bu sorunu sonunda aşamamıştım https://github.com/google/importlab/issues/69
    • objdump kullanırsanız verileri ELF dosyasında kodlandığı haliyle çıktılar
      vdso’nun arayacağı kütüphane listesi bile buna dahil
  • Benzer bir araç olarak lddtree var
    https://github.com/gentoo/pax-utils/tree/master

  • Eksik bağımlılıkları ldd ile özyinelemeli şekilde tekrar tekrar izlemek epey sıkıcı
    Bu yüzden bu iyi bir iyileştirme gibi görünüyor; bir dahaki belirsiz not found durumunda denemeyi düşünüyorum

  • Temelde depends.exe’nin Linux CLI sürümü gibi

    • O belirli araç artık güncel Windows sürümlerinde pek iyi çalışmıyor
      Onun yerine https://github.com/lucasg/Dependencies kullanmak daha iyi. O da tamamen güncel sayılmaz ama…
      Visual Studio kuruluysa ve kurulum yöneticisinde x64/x86 build tools (latest) seçildiyse, VS Developer Command Prompt’ta dumpbin /dependents çalıştırmak hâlâ en güvenilir seçenek
    • Evet, benim de aklıma tam olarak bu gelmişti
      [1] https://www.dependencywalker.com/
  • Renklerin ne anlama geldiğini merak edenler için yazayım; manpage/README’de bulamadım
    macenta: dışlama listesinde, yalnızca -v[v[v]] ile gösteriliyor
    mavi: daha önce görülmüş öğe; böylece birden fazla kez görünen bağımlılıkları bulabilirsiniz

  • “Kütüphanenin neden bulunup bulunmadığı” ne demek? Ya LD_LIBRARY_PATH içindedir ya değildir, değil mi?
    Sadece ekran görüntüsüne bakınca bunun neyi kastettiğini pek anlayamadım

    • Bu aracın bağlamında tam olarak bilmiyorum ama kütüphane arama tek bir ortam değişkeninden çok daha karmaşık
      Sistem arama yolları, runpath, rpath, LD_LIBRARY_PATH vb. farklı dizin arama yöntemleri var
      Kütüphaneler genelde foo.so gibi kısa adlarla bağlanır, ama kütüphanenin tam yolu ile dinamik olarak bağlanmaları da mümkün
      Ek olarak, genel olarak LD_LIBRARY_PATH ayarlamaktan kaçınabiliyorsanız kaçınmak çok daha iyidir. Her zaman mümkün değildir ama ayarladığınızda tüm çalıştırmalarda arama önceliğinin en üstüne çıkar. Bir şey kütüphanenin tam yolu ile dinamik bağlanmış olsa bile LD_LIBRARY_PATH öncelik kazanır ve arama yöntemini tamamen düzleştirir
    • Bir kütüphanenin bulunması için mutlaka LD_LIBRARY_PATH içinde olması gerekmez
      Başlıktaki ana fikir, libtree’nin yürütülebilir dosyadan tüm doğrudan ve dolaylı bağımlılıklara giden yolu kolayca bulmanızı sağlaması. Kullanım alanlarından biri de eksik bağımlılık sorunlarını anlamaya yardımcı olması
      Gerçekte bir paket sistemi kullanıyorsanız bağımlılıkların eksik olması pek olası değildir; bu yüzden libtree’yi muhtemelen başka nedenlerle kullanırsınız
    • Mesele yalnızca LD_LIBRARY_PATH içinde olup olmaması değil; her kütüphane için yükleme anında değerlendirilen RPATH de var
      Daha büyük nokta şu: bağımlılıklar bir grafik oluşturur ve bu, ağaç gibi gösterilebilir. Belirli bir kütüphanenin bulunamamasına hangi kütüphanenin onu gerektirmesinin yol açtığını bilmek yararlıdır
    • Kütüphaneler yalnızca LD_LIBRARY_PATH ile bulunmaz. Yükleyici, kütüphaneleri bulmak için başka birçok kaynağı da dikkate alır
      Normal bir yapılandırmada bu, yüklenen her ikilinin genel ELF alanları ile yükleyicinin bildiği diğer yolların birleşimidir
      Aynı kütüphanenin birden çok sürümünün veya aynı ada sahip birden çok kütüphanenin olduğu sistemlerde LD_LIBRARY_PATH’e güvenmek çok dar görüşlü olabilir. Yükleyici her ikili için LD_LIBRARY_PATH içindeki yolları sırayla arar ve eşleşen ilk kütüphaneyi seçer. Başka bir yöntemle daha yüksek öncelikli yollar ayarlamadıysanız, bu kütüphane aslında istediğiniz şey olmayabilir ve çalışma zamanında beklenmeyen hatalara yol açabilir
      Daha iyi yöntem, ilgili ikili için gereken kütüphanelerin bulunduğu konuma RPATH ayarlamaktır
      Ortam ve RPATH ayarları tutarsızsa aynı kütüphanenin birden çok sürümünü aynı anda yüklemeniz de mümkün. Bu araç, bir sorun olup olmadığını ve nedenini anlamaya yardımcı olur
    • En azından RPATH, RUNPATH ve LD_LIBRARY_PATH var
      Bu araç ldd tabanlı olduğundan muhtemelen DYLD_LIBRARY_PATH, DYLD_FALLBACK_FRAMEWORK_PATH, DYLD_FALLBACK_LIBRARY_PATH, @executable_path, @loader_path, @rpath öğelerini de çözümler
  • Gerçekten yararlı. Genelde asıl gereksinimlerin ne olduğunu anlamak için readelf ile bölümleri okurum

  • LD_DEBUG=libs yetmiyor mu?

    • O, kütüphane bağımlılıklarının statik değerlendirmesi değil, yükleyici hata ayıklama bayrağı; bu yüzden tam olarak aynı şey değil
  • Hata mı bilmiyorum ama vim örneğinde ldd ve libtree farklı kütüphaneler gösteriyor
    Örneğin linux-vdso.so.1, ldd çıktısında listenin en üstünde görünüyor ama libtree’de hiç yok

    • linux-vdso.so.1, dosya sisteminde bir yerde bulunabilecek gerçek bir kütüphane değildir ve ELF dosyasında da referans verilmez; bu yüzden libtree bunu bilemez
      Bunun yerine çekirdek, yeni başlatılan sürecin adres alanına otomatik olarak eşler. gettimeofday gibi işlevlerde sistem çağrısı ek yükünden kaçınmaya yönelik bir optimizasyondur. Referans: https://man7.org/linux/man-pages/man7/vdso.7.html
  • NixOS’ta kapalı kaynak bir ikiliyi çalıştırmak için neleri dahil etmem gerektiğini anlamak amacıyla ldd’yi özyinelemeli çalıştıran berbat küçük bir betik yazmıştım
    Tekrar böyle bir şey yapmam gerekirse bu aracı denemeyi düşünüyorum

 
kayws426 2024-06-11

Güzel görünüyor!!