내 공유 라이브러리에 중복된 기호가 있는 이유(및 방법)는 무엇입니까?

내 공유 라이브러리에 중복된 기호가 있는 이유(및 방법)는 무엇입니까?

내보낸 공유 라이브러리 기호의 단순 목록에서 어떤 라이브러리가 어떤 기호를 내보냈는지 알아내야 했습니다. 목록에는 각 기호를 수동으로 상호 참조할 수 없을 만큼 충분한 기호(20개 정도)가 있었습니다.

나는 이것이 유용한 출력을 생성하는 것 같다는 것을 알았습니다 . 두 번째 열에 주소도 나열되어 nm -A -D -f sysv <library-name>있는 줄을 검색할 수 있었습니다 . FUNC그래서 의 모든 항목에 대해 이 명령을 실행하여 /usr/lib파일로 리디렉션했습니다.

놀랍게도 파일을 구문 분석하기 위해 만든 스크립트의 온전성 검사에서 중복된 기호가 있다고 보고되었습니다! 조사해본 결과,라이브러리가 중복 기호를 내보내는 것으로 나타났습니다?!?

나는 일부 쉘 스크립팅을 사용하여 이것을 확인했고, 내가 사용한 명령을 다음과 같이 바꿀 수 있었습니다 (기술적으로) 짧막 한 농담:

readlink -f /lib/* /usr/lib/* \
  | grep -F .so. | sort | uniq \
  | while read x; do nm -A -D -f sysv $x; done \
  | grep FUNC | cut -d'|' -f1 | sort -g | uniq -c | sort -g \
  | sed -n '/^ \+1/!{s/^ \+[0-9]\+ \+//p}' | sed 's/ //g' \
  | tr '\n' '\v' \
  | sed ':1;s/\([^ ]\+\):\([^\v$]\+\)\v\1:/\1:\2|/g;t1' \
  | tr '\v' '\n' \
  | while IFS=: read -a x; do \
     nm -A -D -f sysv "${x[0]}" | grep ":\\(${x[1]//|/\\|}\\).*FUNC"; \
  done

위의 명령은 짧은 시간 동안 디스크를 탐색하게 합니다. 원하는 경우 임시 파일로 리디렉션되는 청크로 나눌 수 있습니다. 또한출력이 매우 넓을 것입니다(~150열).

나는 처음에 내가 작업하고 있던 Debian Squeeze chroot에서 원래 스크립트를 실행했지만 호기심 때문에 chroot가 제정신이 아닌지 알아보기 위해 호스트 시스템에서 위의 스크립트를 실행했습니다.

음... chroot는 90개가 넘는 중복 항목을 보고했지만 내 호스트(Arch) 시스템에는 약 267개가 있는 것 같습니다.

이 명령은 의 출력을 grepping하여 작동하므로 nm결과는 약간 시끄럽지만 다음과 같습니다.

/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|00043700|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|000436c0|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access_mask|000458f0|   T  |              FUNC|00000058|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|000432a0|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|00043260|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00044ff0|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00045030|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|000453c0|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|00045380|   T  |              FUNC|0000003c|     |.text

각 기호가 어떻게 두 개 있는지 확인하세요.주소가 다릅니다, 네, 하지만... 저는 동적 연결이 심볼 이름으로 작동하는 줄 알았는데 그게 전부였습니다. (위 목록에서 오른쪽으로 스크롤하면) 기호가 모두 FUNC해당 섹션의 유형이라는 사실로 인해 혼란이 더욱 가중됩니다 .text.

저는 여기 내부에서 어떤 흥미로운 마법이 일어나고 있는지 알아보기 위해 이 글을 게시하고 있습니다. (시스템이 작동하고 있어서...)

약 600줄의 텍스트를 덤프할 수 있는 좋은 아이디어가 있는 사람이 있다면 Pastebin은 더 이상 유행하지 않는 것 같고 저는 GitHub를 사용하지 않습니다. 전체 출력을 기꺼이 공유하겠습니다.

답변1

에서 제공한 정보가 nm불완전하기 때문에 기호가 중복되어 나타납니다. 문제의 기호에는 버전이 지정되어 있습니다. 다음을 사용하여 이를 볼 수 있습니다 objdump -T.

0000000000059d00 g    DF .text  0000000000000044 (ALSA_0.9)   snd_pcm_hw_params_get_access
0000000000056040 g    DF .text  000000000000004b  ALSA_0.9.0rc4 snd_pcm_hw_params_get_access

또는 nm님의 --with-symbol-versions옵션:

/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000059d00|   T  |              FUNC|0000000000000044|     |.text@ALSA_0.9
/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000056040|   T  |              FUNC|000000000000004b|     |.text@@ALSA_0.9.0rc4

바이너리는 특정 버전의 기호에 대해 연결되며 링크 시 올바른 버전을 얻습니다. 이를 통해 이전 버전과의 호환성을 유지하면서 API를 변경할 수 있습니다.

관련 정보