programing

libc static과 다른 라이브러리를 동적으로 연결하는 GCC, 재검토?

powerit 2023. 9. 20. 20:47
반응형

libc static과 다른 라이브러리를 동적으로 연결하는 GCC, 재검토?

다음 질문은 관련이 있지만 제 질문에 대답하지 않습니다.

GCC에서 부분적으로 정적이고 부분적으로 동적인 링크

동적 라이브러리를 다른 정적 라이브러리에 연결하는 정적 라이브러리에 연결

GCC: 일부 라이브러리만 정적으로 연결

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 공유 라이브러리 기능의 정적 링크

둘 다 안 돼요.

기본적으로 첫 번째 접근 방식이 올바른 방법입니다.

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

반응형