Linux의 함수는 런타임 시 어떻게 구문 분석되나요? 순전히 이름 기반이고 제가 상상하는 "기호 테이블"인가요, 아니면 일종의 하드코딩된 주소인가요? Musl libc 및 glibc에 대해 다시 컴파일해야 한다는 내용을 온라인에서 읽었지만 동일한 기호 내보내기가 있어서는 안 되나요? 기호는 어떻게 작동하나요?
답변1
프로그램은 런타임 전에 메모리에 로드되므로 함수는 기본 주소를 기준으로 특정 메모리 주소에 매핑됩니다. 함수에 대한 모든 호출은 상대 메모리 주소로 컴파일됩니다. 기호 테이블은 일반적으로 바이너리에 포함되지만 주소 매핑은 디버깅 목적을 위해 사람이 읽을 수 있는 이름으로 반전됩니다. nm -D /usr/lib/libc.so.6
glibc의 기호 테이블을 보려면 일반적인 Linux 설치를 시도해 보십시오 .
바이너리 호환성 측면에서 glibc와 Musl은 모두 공유 표준을 구현하지만 자체 헤더 파일에 반영되어야 하는 다양한 기능을 가지고 있습니다. 따라서 대부분의 Linux 배포판에는 공통 표준 라이브러리 헤더 패키지가 없는 이유가 있습니다. 대신 각 라이브러리와 함께 번들로 제공됩니다. ).
musl의 FAQ:
musl은 glibc와 호환됩니까?
예, 아니오. 소스 코드와 바이너리 수준에서 musl의 목표는 버그 호환성보다는 glibc와 어느 정도 기능적 호환성을 달성하는 것입니다. glibc를 사용하는 애플리케이션이 musl에 대해 컴파일에 실패하는 경우 그 이유는 일반적으로 다음 중 하나입니다.
- 하나의 헤더를 포함하면 관련되지 않은 다른 헤더의 기호가 노출되는 것으로 가정됩니다. 이는 애플리케이션 오류이며 누락된 #include 지시어를 추가하는 것만큼 쉽게 수정할 수 있습니다.
- 애플리케이션에 노출되어서는 안되는 glibc 헤더의 구현 세부 정보를 사용하세요. 이는 애플리케이션 오류이기도 하며 일반적으로 검색 및 바꾸기(예: 소스 코드에서 __pid_t를 pid_t로 바꾸기)를 통해 해결할 수 있습니다.
- musl에서 구현되지 않은 인터페이스를 사용하십시오. 이 문제는 애플리케이션의 인터페이스 사용을 선택적으로 만들거나 누락된 인터페이스를 지원하도록 musl을 확장함으로써만 해결될 수 있습니다.
바이너리 호환성은 더 제한적이지만 새로운 버전의 musl에서는 꾸준히 개선될 것입니다. 현재 일부 glibc 연결 공유 라이브러리는 musl을 사용하여 로드할 수 있지만 musl이 /lib/ld-linux.so.2 위치에 있으면 가장 간단한 glibc 연결 응용 프로그램을 제외한 모든 응용 프로그램이 실패합니다.