Önceden derlenmiş bir ikili dosyadaki 'rpath'i değiştirebilir miyim?


96

Hurda yığını için planlanmış eski bir yürütülebilir dosyam var, ancak henüz orada değil. Çevremden kaldırılan bazı kitaplara dayanıyor, ancak iyi çalıştığı bir yerde bazı saplamalarım var. Bu yürütülebilir dosyayı bu saplama kitaplarına yönlendirmek istiyorum. Evet, LD_LIBRARY_PATH ayarlayabilirim, ancak bu yürütülebilir dosya birçok komut dosyasından çağrılır ve birçok kullanıcı ve bunu tek bir noktada düzeltmeyi çok isterim.

Bunun için kaynağım yok ve onu elde etmek zor olurdu. Düşünüyordum da - ELF duyarlı bir düzenleyici kullanarak bu dosyayı düzenleyebilir miyim ve rpath'e yeni kütüphanelere ulaşması için basit bir PATH ekleyebilir miyim? Bu mümkün mü, yoksa bir ELF ikili dosyası oluşturduğunuzda, şeyleri konumlara sabitlersiniz ve taşınamazlar mı?


3
LD_LIBRARY_PATH'yi ayarlayan ve ikiliyi çağıran bir kabuk komut dosyasına sarın. Kabuk betiğini arayanların PATH'ındaki bir yere koyun.
wildplasser

LD_LIBRARY_PATH, alt süreçler tarafından miras alınır. Bunu istemeyebilirsin.
Will

1
@ evet olacak ve bunu yapmak istemediğimi zaten söyledim. :)
Rich Homolka

Yanıtlar:


82

Bunu chrpathyapabilen bir araç var - muhtemelen dağıtımınızın paketlerinde mevcut.


9
Mac kullanıcıları için sadece bir not install_name_tool, bunu -rpathbayrakla yapabilir
Kevin Tonon

10
Eğer hata alırsanız: <binary>: no rpath or runpath tag found., kullanmak olamaz chrpathdeğiştirmek, ancak kullanabilirsiniz patchelfbu durumda:patchelf --set-rpath /path/to/libaries <binary>
phyatt

Mümkünse chrpath'i tercih ederim, çünkü daha evrensel olsa da, patchelf'in kütüphanelerinizin / çalıştırılabilir dosyalarınızın boyutunu önemli ölçüde artıran bazı uzun süredir devam eden bir hatası vardır.
taranaki

@taranaki: Patchelf'in hangi sürümünden bahsediyorsunuz?
hagello

1
chrpath'in ciddi bir sınırlaması var: RPATH'ı yalnızca eşit veya daha kısa uzunlukta bir RPATH ile değiştirebilir (rpath sürüm 0.16'nın man sayfası)
hagello

167

chrpathÇağrılandan daha evrensel bir araç var patchelf. Başlangıçta Nix ve NixOS (paketleme sistemi ve bir GNU / Linux dağıtımı) için paketler oluşturmada kullanılmak üzere oluşturuldu.

İkili dosyada rpath olmaması durumunda (burada rdsamp olarak adlandırılır), chrpathbaşarısız olur:

chrpath -r '$ORIGIN/../lib64' rdsamp 
rdsamp: no rpath or runpath tag found.

Diğer yandan,

patchelf --set-rpath '$ORIGIN/../lib64' rdsamp

gayet başarılı.


10
Özellikle, patchelfhenüz bir rpath içermeyen bir ikiliye bir rpath ekleyebilir - chrpathsadece halihazırda mevcut bir girişi değiştirebildiği görülüyor.
maxschlepzig

5
Genel bir not olarak, rpathve arasındaki ince ayrımı anlamaya değer runpath. Temel olarak, biri geçersiz kılabilir LD_LIBRARY_PATHve diğeri olamaz. Ayrıntılar için bkz. Blog.tremily.us/posts/rpath
Stuart Berg

6
Can sıkıcı şey hem olmasıdır chrpathve patchelfonların terminolojisi ile özensiz. Örneğin, patchelfyukarıda gösterilen komut değişecek runpathancak rpathsiz --force-rpathseçeneği de sağlamadığınız sürece değişmeyecektir .
Stuart Berg

10
@superbatfish Evet, ancak fark genellikle önemli değil. Arasında CHANGELOG dan Bu giriş patchelf": bu açıklar --set-rpath, --shrink-rpathve --print-rpathşimdi tercih DT_RUNPATHüzerinde DT_RPATHeskimiş olan her iki varsa güncellenmesi, hem güncellenir zaman tek DT_RPATH varsa, o dönüştürülür.. DT_RUNPATHOlmadıkça --force-rpathbelirtilirse ne mevcuttur. , belirtilmediği DT_RUNPATHsürece a eklenir --force-rpath, bu durumda a DT_RPATHeklenir. " Seçeneğin adı muhtemelen uyumluluk nedenleriyle değiştirilmeden tutuldu.
user7610

2
Şimdiye kadar en iyi cevap, bunun yerine kabul edilen cevap olmalı!
Kenneth Hoste

19

@ User7610'un dediği gibi, gitmenin doğru yolu patchelfaraçtır.

Ancak, tam olarak bunu yapmak için gereken tüm komutları kapsayan daha kapsamlı bir cevap verebileceğimi hissediyorum.

Konuyla ilgili kapsamlı bir makale için burayı tıklayın

Her şeyden önce, birçok geliştirici hakkında konuşuyor RPATH, ama aslında kastediyorlar RUNPATH. Bunlar iki farklı isteğe bağlı dinamik bölümdür ve yükleyici bunları çok farklı şekilde ele alır. Daha önce bahsettiğim bağlantıda aralarındaki fark hakkında daha fazla bilgi edinebilirsiniz.

Şimdilik şunu unutmayın:

  • Eğer RUNPATHayarlanmışsa, RPATHyok sayılır
  • RPATH kullanımdan kaldırıldı ve kaçınılması gerekiyor
  • RUNPATH tarafından geçersiz kılındığı için tercih edilir LD_LIBRARY_PATH

Mevcut R [UN] YOLUNU görün

readelf -d <path-to-elf> | egrep "RPATH|RUNPATH"

R [UN] YOLUNU temizleyin

patchelf --remove-rpath <path-to-elf>

Notlar:

  • Hem RPATHve hem deRUNPATH

R [UN] YOLUNA değer ekleyin

patchelf [--force-rpath] --set-rpath "<desired-rpath>" <path-to-elf>

Notlar:

  • <desired-path> virgülle ayrılmış bir dizinler listesidir, örneğin: /my/libs:/my/other/libs
  • Eğer belirtirseniz --force-rpath, ayarlar RPATH, aksi halde ayarlarRUNPATH

1
-Wl,-R,<desired-rpath> -Wl,--enable-new-dtagssetler DT_RUNPATHve bu çoğu insanın kullanması gereken şey. RUNPATHtarafından geçersiz kılınabilir LD_LIBRARY_PATH, bu yüzden millet kullanmamalıdır --force-rpath.
jww

@jww RPATH'ın kullanımdan kaldırılmasıyla ilgili bir yorum eklemediğimi görüyorum, bu yüzden şimdi bir tane ekledim. Teşekkürler!
Daniel Trugman

Örnekte <desired-path>iki nokta üst üste kullanıldığına dikkat edin; virgül olmalıdır (yani:) /my/libs,/my/other/libs.
Alan De Smet

@AlanDeSmet, virgül hakkında bilmiyorum ama iki nokta üst üste bende çalışıyor.
Daniel Trugman

RPATH kullanımdan kaldırılmış olabilir, ancak RUNPATH kullanımı "beklenmedik" köşe durumlarına yol açabilir. Örneğin bkz . Qt.io/blog/2011/10/28/rpath-and-runpath .
Rob

0

Bu, XORIGIN'i $ ORIGIN ile değiştirerek benim için çalıştı.

chrpath -r '\$\ORIGIN/../lib64' httpd

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.