이미 컴파일 된 바이너리에서 'rpath'를 변경할 수 있습니까?


92

스크랩 힙에 대해 예약 된 오래된 실행 파일이 있지만 아직 없습니다. 내 환경에서 제거 된 일부 라이브러리에 의존하지만 제대로 작동하는 어딘가에 스텁 라이브러리가 있습니다. 이 실행 파일을 이러한 스텁 라이브러리로 가리키고 싶습니다. 예, LD_LIBRARY_PATH를 설정할 수 있지만이 실행 파일은 많은 스크립트에서 호출되며 많은 사용자가 한곳에서 수정하고 싶습니다.

나는 이것에 대한 출처가 없으며 그것을 얻기가 어려울 것입니다. 나는 생각하고 있었다-ELF 인식 편집기를 사용하여이 파일을 편집하고 rpath에 간단한 PATH를 추가하여 새 라이브러리에 맞출 수 있습니까? 이것이 가능합니까, 아니면 ELF 바이너리를 만든 후에는 위치를 수정하고 이동할 수 없습니까?


3
LD_LIBRARY_PATH를 설정하고 바이너리를 호출하는 쉘 스크립트로 래핑합니다. 호출자의 PATH에있는 위치에 쉘 스크립트를 넣으십시오.
wildplasser 2012

LD_LIBRARY_PATH는 하위 프로세스에 상속됩니다. 당신은 그것을 원하지 않을 수도 있습니다.

1
@will 예 그리고 나는 이미 그것을하고 싶지 않다고 말했습니다. :)
Rich Homolka

답변:


78

chrpath이를 수행 할 수 있는 도구 가 있습니다. 배포판의 패키지에서 사용할 수 있습니다.


9
그냥 맥 사용자를위한 참고 install_name_tool이 할 수있는 -rpath플래그
케빈 TONON

10
오류가 발생하면을 ( 를) 교체하는 데 <binary>: no rpath or runpath tag found.사용할 수 없지만 이 경우에는 chrpath사용할 수 있습니다 patchelf.patchelf --set-rpath /path/to/libaries <binary>
phyatt

가능한 경우 chrpath를 선호합니다. 더 보편적이지만 patchelf에는 라이브러리 / 실행 파일의 크기를 크게 늘리는 오랜 버그가 있기 때문입니다.
taranaki

157

chrpath라는 것보다 더 보편적 인 도구가 patchelf있습니다. 원래 Nix 및 NixOS (패키징 시스템 및 GNU / Linux 배포판) 용 패키지를 만드는 데 사용하기 위해 만들어졌습니다.

바이너리 (여기서는 rdsamp라고 함)에 rpath가없는 경우 chrpath실패합니다.

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

반면에

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

잘 성공합니다.


9
특히 patchelfrpath를 포함하지 않는 바이너리에 rpath를 추가 할 수 chrpath있지만 이미 존재하는 항목 만 수정할 수있는 것처럼 보입니다.
maxschlepzig 2014

4
일반적으로 rpath와 사이의 미묘한 차이를 이해하는 것이 runpath좋습니다. 기본적으로 하나는 재정 LD_LIBRARY_PATH의 할 수 있고 다른 하나는 무시할 수 있습니다 . 자세한 내용은 blog.tremily.us/posts/rpath를
Stuart Berg

6
성가신 일이 모두 있다는 것입니다 chrpath그리고 patchelf자신의 용어에 실수 있습니다. 예를 들어 patchelf위에 표시된 명령 은 옵션을 제공 runpath하지 rpath않는 한 변경 되지 않습니다 --force-rpath.
Stuart Berg

10
@superbatfish 예,하지만 일반적으로 차이는 중요하지 않습니다. 의 CHANGELOG에서이 항목은 patchelf"그것을 설명하지 --set-rpath, --shrink-rpath그리고 --print-rpath지금 선호 DT_RUNPATH이상 DT_RPATH사용되지 않습니다, 이는 모두가있는 경우, 업데이트, 모두 업데이트하는 경우에만 DT_RPATH가있는 경우,이 변환됩니다.. DT_RUNPATH하지 않는 한 --force-rpath지정된 경우 어느 쪽도 존재한다. , a DT_RUNPATH--force-rpath지정 되지 않는 한 DT_RPATH추가됩니다. 이 경우 a 가 추가됩니다. " 옵션의 이름은 호환성을 위해 변경되지 않았을 것입니다.
user7610

2
단연코 가장 좋은 대답은 이것이 허용되는 대답이어야합니다!
Kenneth Hoste

12

@ user7610이 말했듯이 올바른 방법은 patchelf도구입니다.

그러나 나는 정확히 그것을 수행하는 데 필요한 모든 명령을 포함하여보다 포괄적 인 답변을 줄 수 있다고 생각합니다.

주제에 대한 포괄적 인 기사를 보려면 여기를 클릭 하십시오.

우선, 많은 개발자들이에 대해 이야기 RPATH하지만 실제로는 RUNPATH. 이들은 두 개의 다른 선택적 동적 섹션이며 로더는 매우 다르게 처리합니다. 앞서 언급 한 링크에서 이들의 차이점에 대해 자세히 알아볼 수 있습니다.

지금은 기억하세요 :

  • 경우 RUNPATH설정, RPATH무시됩니다
  • RPATH 더 이상 사용되지 않으며 피해야합니다.
  • RUNPATH 재정의 될 수 있기 때문에 선호됩니다. LD_LIBRARY_PATH

현재 R [UN] PATH보기

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

R [UN] PATH 지우기

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

노트:

  • 삭제 모두 RPATHRUNPATH

R [UN] PATH에 값 추가

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

노트:

  • <desired-path> 쉼표로 구분 된 디렉토리 목록입니다. 예 : /my/libs:/my/other/libs
  • 지정하면 --force-rpath, sets RPATH, 그렇지 않으면 설정RUNPATH

1
-Wl,-R,<desired-rpath> -Wl,--enable-new-dtags세트 DT_RUNPATH, 그리고 그것은 대부분의 사람들이 사용해야하는 것입니다. RUNPATH에 의해 재정의 될 수 LD_LIBRARY_PATH있으므로 사람들은 --force-rpath.
jww

@jww RPATH의 사용 중단에 대한 설명을 추가하지 않았으므로 방금 추가했습니다. 감사!
Daniel Trugman

이 예 <desired-path>에서는 콜론을 사용합니다. 쉼표 (즉 :) 여야합니다 /my/libs,/my/other/libs.
Alan De Smet

@AlanDeSmet, 나는 쉼표에 대해 모르지만 콜론은 나를 위해 작동합니다.
Daniel Trugman

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.