32비트 Linux 시스템에서는 다음을 호출하세요.
$ /lib/libc.so.6
64비트 시스템의 경우
$ /lib/x86_64-linux-gnu/libc.so.6
셸에서 다음 출력을 제공합니다.
GNU C Library stable release version 2.10.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.0 20090506 (Red Hat 4.4.0-4).
Compiled on a Linux >>2.6.18-128.4.1.el5<< system on 2009-08-19.
Available extensions:
The C stubs add-on version 2.1.2.
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
RT using linux kernel aio
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
이런 일이 발생하는 이유와 방법은 무엇이며, 다른 공유 라이브러리에서도 동일한 작업을 수행하려면 어떻게 해야 합니까?
/usr/lib
실행 파일을 찾아보니 /usr/lib/libvlc.so.5.5.0
실행 결과가 나왔습니다.세그멘테이션 오류. :-/
답변1
라이브러리에는 main()
함수 또는 이에 상응하는 진입점이 있으며 실행 파일과 공유 개체로 모두 사용할 수 있는 방식으로 컴파일됩니다.
이것은추천나에게는 작동하지 않지만 이를 수행하는 방법에 대해.
이것은 또 다른 것입니다SO에 대한 유사한 질문에 대한 답변, 뻔뻔하게 표절하고, 수정하고, 설명을 추가하겠습니다.
먼저, 예제 라이브러리의 소스는 다음과 같습니다 test.c
.
#include <stdio.h>
void sayHello (char *tag) {
printf("%s: Hello!\n", tag);
}
int main (int argc, char *argv[]) {
sayHello(argv[0]);
return 0;
}
컴파일:
gcc -fPIC -pie -o libtest.so test.c -Wl,-E
여기서 우리는 공유 라이브러리( -fPIC
)를 컴파일하지만 링커에게 그것이 일반 실행 파일임을 알리고( ) 효율적으로 링크될 수 있도록 -pie
심볼 테이블을 내보낼 수 있도록( ) 만듭니다 .-Wl,-E
그리고 file
공유 객체라고 할지라도 실행 파일로 작동합니다.
> ./libtest.so
./libtest.so: Hello!
이제 동적 연결이 실제로 가능한지 확인해야 합니다. 예제 프로그램 program.c
:
#include <stdio.h>
extern void sayHello (char*);
int main (int argc, char *argv[]) {
puts("Test program.");
sayHello(argv[0]);
return 0;
}
이를 사용하면 extern
헤더를 생성할 필요가 없어집니다. 이제 컴파일하세요:
gcc program.c -L. -ltest
libtest.so
실행하기 전에 동적 로더에 경로를 추가해야 합니다 .
export LD_LIBRARY_PATH=./
지금:
> ./a.out
Test program.
./a.out: Hello!
ldd a.out
에 대한 링크가 표시 됩니다 libtest.so
.
이것이 glibc가 실제로 컴파일되는 방식이라고 의심됩니다. glibc 자체만큼 이식성이 높지는 않지만( man gcc
및 -fPIC
스위치 참조 -pie
) 기본 메커니즘을 보여주기 때문입니다. 실제 세부 사항을 알려면 소스 makefile을 살펴봐야 합니다.
답변2
GitHub의 임의 glibc 저장소에서 답변을 찾아보겠습니다. 이 버전은 파일에 "배너"를 제공합니다.version.c
.
동일한 파일에는 몇 가지 흥미로운 점이 있습니다. __libc_print_version
텍스트를 표준 출력으로 인쇄하는 기능과 __libc_main (void)
진입점으로 문서화된 기호입니다. 따라서 라이브러리를 실행할 때 이 기호가 호출됩니다.
그렇다면 링커나 컴파일러는 이것이 진입점 함수라는 것을 어떻게 정확히 알 수 있을까요?
더 깊이 파헤쳐보자파일 생성. 링커 플래그 중에는 흥미로운 플래그가 있습니다.
# Give libc.so an entry point and make it directly runnable itself.
LDFLAGS-c.so += -e __libc_main
이는 라이브러리 진입점을 설정하는 데 사용되는 링커 플래그입니다. 라이브러리를 빌드할 때 -e function_name
링커에 플래그를 제공하여 실행 가능한 동작을 활성화할 수 있습니다. 정확히 어떤 역할을 하나요? 우리에게 보여줘수동(다소 오래되었지만 여전히 유효함):
링커 명령 언어에는 출력 파일의 첫 번째 실행 가능 명령(해당 진입점)을 정의하기 위해 특별히 설계된 명령이 포함되어 있습니다. 인수는 상징적인 이름입니다.
입력(기호)
기호 할당과 마찬가지로 ENTRY 명령은 명령 파일에 독립 실행형 명령으로 배치하거나 SECTIONS 명령 내의 섹션 정의에 배치할 수 있습니다(레이아웃에 가장 적합한 위치).
ENTRY는 진입점을 선택하는 여러 방법 중 하나일 뿐입니다. 다음 방법 중 하나로 이를 표시할 수 있습니다(우선순위 내림차순으로 표시됨: 목록에서 더 높은 메소드가 더 낮은 메소드를 대체함).
the `-e' entry command-line option; the ENTRY(symbol) command in a linker control script; the value of the symbol start, if present; the address of the first byte of the .text section, if present; The address 0.
예를 들어, 다음 규칙을 사용하여 할당문으로 진입점을 생성할 수 있습니다. 입력 파일에 시작 기호가 정의되어 있지 않으면 간단히 정의하여 적절한 값을 할당할 수 있습니다.
시작 = 0x2020;
이 예에서는 절대 주소를 보여 주지만 어떤 표현식이라도 사용할 수 있습니다. 예를 들어 입력 개체 파일이 진입점으로 다른 기호 이름 규칙을 사용하는 경우 시작하려는 시작 주소가 포함된 기호의 값을 할당할 수 있습니다.
시작 = 기타 기호;
(현재 문서를 찾을 수 있습니다여기)
ld
-e
명령줄 옵션 (가장 널리 사용되는 솔루션) 을 제공하거나 , 함수 기호를 제공 start
하거나, 어셈블러에 대한 기호 주소를 지정하는 경우 링커는 실제로 진입점 함수가 있는 실행 파일을 만듭니다.
그러나 다른 링커와의 작동이 보장되지는 않는다는 점에 유의하십시오(llvm의 lld에 동일한 플래그가 있는지는 모르겠습니다). 왜 이것이 SO 파일에 대한 정보를 제공하는 것 이외의 목적을 가지고 있는지 모르겠습니다.