libc static과 다른 라이브러리를 동적으로 연결하는 GCC, 재검토?
다음 질문은 관련이 있지만 제 질문에 대답하지 않습니다.
동적 라이브러리를 다른 정적 라이브러리에 연결하는 정적 라이브러리에 연결
아까도 아주 비슷한 질문을 했는데, 제가 시작한 이전 질문이 댓글란에서 다소 어수선해져서 충분히 답변하지 못했기 때문에 (하지만 좋은 노력이었고 적어도 부분적으로 답변을 했기 때문에 답변한 것으로 표시했습니다) 새로운 질문을 하겠습니다.문제는 특히 다른 라이브러리(예: libm)를 동적으로 연결하면서 libc를 정적으로 연결하는 방법입니다.이것은 첫 번째 질문에서 할 수 없는 것으로 제안되었는데, 사실입니까?그렇다면 왜 안 되는지 알면 아주 흥미로울 것 같습니다.
이것이 가능하긴 합니까?누군가가 그것이 가능하다고 코멘트를 했지만(어떤 이유로 제거되었습니까?), 동적 라이브러리에 의해 요구되기 때문에(예: 동적 libm은 동적 libc(?)) 동적 libc가 필요할 것이기 때문에 동적으로 연결된 libc 버전도 존재해야 합니다.
이것은 저에게는 괜찮지만, GCC에게 이것을 어떻게 하라고 말해야 하는지 명확하지 않습니다. 즉, 정적인 상태와 동적인 상태 모두로 libc의 링크입니다.어떻게 해야 하나요? (몇 가지 시도를 했는데 일부는 질문 뒤에 나와 있습니다.)아니면 제가 원하는 것을 할 수 있는 다른 방법이 있을까요?
먼저 gcc test.c-lm을 실행하면 다음과 같이 모든 것이 동적으로 연결됨을 알 수 있습니다.
$ gcc test.c -lm
$ ldd a.out
linux-vdso.so.1 (0x00007fffb37d1000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)
libc를 동적으로 유지하면서 libc만 정적으로 연결하려면 다음을 수행할 수 있습니다(Z boson이 앞서 언급한 질문 중 하나에서 지적한 바와 같이).
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a
$ ldd a.out
linux-vdso.so.1 (0x00007fff747ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)
그러나 libc static과 libm dynamic을 연결하기 위해 동일한 절차를 시도하는 것은 효과가 없는 것으로 보입니다.
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
이 오류 메시지는 무엇을 의미합니까?
몇 가지 다른 시도(대부분은 첫 번째 질문에도 포함되었습니다):
$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bdynamic -lm -Wl,-Bstatic -lc test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bstatic -lc -Wl,-Bdynamic -lm test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
마지막 것이 컴파일/링크에 성공했습니다.그러나 libc는 정적으로 연결되지 않고 동적으로만 연결되므로 또 다른 실패 시도입니다.
테스트 프로그램은 단순히 다음과 같습니다.
$ cat test.c
#include <stdio.h>
#include <math.h>
int main(int argc, char **argv)
{
int i;
int result;
for(i = 0; i < 65535; i++) {
result = sin(i);
}
return 0;
}
편집:
이 질문에 제시된 것처럼, 저도 통계자와 어민을 시도해 보았습니다.
둘 다 안 돼요.
기본적으로 첫 번째 접근 방식이 올바른 방법입니다.
gcc test.c libc.a -lm
gcc가 암시적 라이브러리를 추가하면 다음과 같이 나타납니다.
gcc crt1.o test.c libc.a -lm -lc -lgcc -lc
이는 libc 에 의해 되는 libc 합니다.crt1.o
아니면test.c
입니다에서 할 libc.a
그리고 정적으로 연결된 반면에, 어떤 함수는 오직libm
아니면libgcc
동적으로 연결됩니다(그러나 libm이 이미 끌어온 것을 호출하면 정적 함수를 다시 사용합니다).
링커는 항상 가장 왼쪽에 있는 파일/라이브러리에서 시작하여 오른쪽으로 작동합니다. 다시는 돌아가지 않습니다..c
그리고..o
되지만,.a
및s-l
는 이미 되지 않은 를 찾는 됩니다.합니다).-lc
두 번이나 나타나야 하기 때문입니다.-lc
에 달려 있습니다-lgcc
,그리고.-lgcc
에 달려 있습니다-lc
링크 순서가 중요합니다!
도 에 하신 것 .strcmp
대신 ) (libc서하는)strcmp
): STT_GNU_IFUNC
기능의 여러 버전을 포함할 수 있는 영리한 기능이며, 사용 가능한 하드웨어에 따라 실행 시 가장 최적의 기능을 선택할 수 있습니다.확실하지는 않지만 이 기능은 PIE(Position Independent Executive) 또는 공유 라이브러리 빌드에서만 사용할 수 있는 것 같습니다.
이 정적인 에 거지?libc.a
만을 하는 것,다:입니다.strcmp
(기본적으로 느린 구현은 C의 몇 줄에 불과합니다.) 먼저 링크를 연결합니다. libc.a
.
gcc test.c mystrcmp.c libc.a -lm
도 있습니다.libc.a
당신이 진정으로 원하는 것과 정적으로 연결하는 것.
ar x libc.a
gcc test.c somefile.o -lm
ar
할 것입니다..a
파일, 다음과 같이tar
할 것입니다..tar
, 의 사용법이 는 하지만,이,만,를 추출합니다..o
일의 :.a
파일을 저장한 다음 명시적으로 연결합니다.
ams의 답변을 바탕으로 다음과 같이 했습니다.
나의 strcmp.c
int strcmp(const char *s1, const char *s2) {
}
컴파일
gcc -c test.c
gcc -c mystrcmp.c
설정 파일
ln -s `gcc -print-file-name=crt1.o`
ln -s `gcc -print-file-name=crti.o`
ln -s `gcc -print-file-name=crtn.o`
ln -s `gcc -print-file-name=libgcc_eh.a`
ln -s `gcc -print-file-name=libc.a`
ln -s `gcc -print-file-name=libm.so`
링크
ld -melf_x86_64 -o math crt1.ocrti.o test.o mystrcmp.olibc.a libgcc_eh.a libc.a libm.so -dynamic-linker /lib64/ld-linux-x86-64.so .2 crtn.o
이 링크는 올바르게 연결되고 실행됩니다.하지만,ldd
드라마들.
linux-vdso.so.1 => (0x00007fff51911000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8182470000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f81820a9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8182793000)
그 역동적인 모습이libm
동적 필요libc
. 사실 그건 보여주기가 쉽잖아요.
ldd libm.그래서 보도합니다.
linux-vdso.so.1 => (0x00007fff20dfe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcaf74fe000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcaf7bed000)
그래서 libm에 링크하는 것은 불가능합니다.따라서 libc에 의존하지 않고 libm을 컴파일하지 않는 한 libc.so 을 링크하지 않아도 됩니다.
쓰임새만
gcc sample_uart.c -static -static-libgcc -static-libstdc++
# lddtree a.out
a.out => ./a.out (interpreter => none)
#################### test ############################
ar x /usr/lib/arm-linux-gnueabihf/libc.a
-rw-r--r-- 1 root root 792 Oct 28 00:38 wmemset.o
-rw-r--r-- 1 root root 2456 Oct 28 00:38 wmemstream.o
-rw-r--r-- 1 root root 1616 Oct 28 00:38 wordcopy.o
-rw-r--r-- 1 root root 18544 Oct 28 00:38 wordexp.o
-rw-r--r-- 1 root root 1384 Oct 28 00:38 wprintf_chk.o
-rw-r--r-- 1 root root 1088 Oct 28 00:38 wprintf.o
-rw-r--r-- 1 root root 884 Oct 28 00:38 write_nocancel.o
-rw-r--r-- 1 root root 1368 Oct 28 00:38 write.o
-rw-r--r-- 1 root root 1340 Oct 28 00:38 writev.o
-rw-r--r-- 1 root root 1084 Oct 28 00:38 wscanf.o
-rw-r--r-- 1 root root 3924 Oct 28 00:38 wstrops.o
-rw-r--r-- 1 root root 2112 Oct 28 00:38 xcrypt.o
-rw-r--r-- 1 root root 1504 Oct 28 00:38 xdr_array.o
-rw-r--r-- 1 root root 836 Oct 28 00:38 xdr_float.o
-rw-r--r-- 1 root root 2344 Oct 28 00:38 xdr_intXX_t.o
-rw-r--r-- 1 root root 1740 Oct 28 00:38 xdr_mem.o
-rw-r--r-- 1 root root 4696 Oct 28 00:38 xdr.o
-rw-r--r-- 1 root root 3880 Oct 28 00:38 xdr_rec.o
-rw-r--r-- 1 root root 1640 Oct 28 00:38 xdr_ref.o
-rw-r--r-- 1 root root 1556 Oct 28 00:38 xdr_sizeof.o
-rw-r--r-- 1 root root 2464 Oct 28 00:38 xdr_stdio.o
-rw-r--r-- 1 root root 1688 Oct 28 00:38 xlocale.o
-rw-r--r-- 1 root root 936 Oct 28 00:38 xmknodat.o
-rw-r--r-- 1 root root 944 Oct 28 00:38 xmknod.o
-rw-r--r-- 1 root root 1052 Oct 28 00:38 xpg_basename.o
-rw-r--r-- 1 root root 1640 Oct 28 00:38 xpg-strerror.o
-rw-r--r-- 1 root root 900 Oct 28 00:38 xstat64.o
-rw-r--r-- 1 root root 1184 Oct 28 00:38 xstatconv.o
-rw-r--r-- 1 root root 1196 Oct 28 00:38 xstat.o
root@hi3798mv100:~/sample/uart#
root@hi3798mv100:~/sample/uart#
root@hi3798mv100:~/sample/uart# gcc sample_uart.c -lm
root@hi3798mv100:~/sample/uart# gcc sample_uart.c *.o -lm
/usr/bin/ld: dso_handle.o:(.data.rel.ro.local+0x0): multiple definition of `__dso_handle'; /usr/lib/gcc/arm-linux-gnueabihf/9/crtbeginS.o:(.data.rel.local+0x0): first defined here
/usr/bin/ld: rcmd.o: in function `__validuser2_sa':
(.text+0x418): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: error: ld returned 1 exit status
언급URL : https://stackoverflow.com/questions/26277283/gcc-linking-libc-static-and-some-other-library-dynamically-revisited
'programing' 카테고리의 다른 글
WC_상품_have_posts()에서 작동하지 않는 쿼리 (0) | 2023.09.20 |
---|---|
PHP PDO 준비문 -- MySQL LIKE 쿼리 (0) | 2023.09.20 |
생성된 XML에서 'standalone="yes" 제거 (0) | 2023.09.20 |
대용량 파일을 처리할 수 있는 Lightweight XML Viewer (0) | 2023.09.20 |
문자열 길이에 따라 문자열 데이터 필터링 (0) | 2023.09.20 |