2014-10-09 3 views
11

다음 질문은 관련이 있지만, 내 질문에 대답하지 않습니다 Static link of shared library function in gcclibc 정적 라이브러리와 다른 라이브러리를 동적으로 링크하는 GCC?

Linking partially static and partially dynamic in GCC

Linking a dynamic library to a static library that links to other static libraries

GCC: static linking only some libraries

내가 이전 매우 비슷한 질문을, 그러나 이전 이후 나에 의해 시작된 질문은 코멘트 섹션에서 다소 복잡해졌으며 완전히 답변되지 않았습니다. (그러나 나는 노력으로 좋았고 적어도 부분적으로 대답했기 때문에 답을 냈다.) 나는 새로운 질문을 할 것이다. 문제는 libc를 정적으로 연결하는 방법과 다른 라이브러리 (예 : libm)를 동적으로 링크하는 방법입니다. 이것은 첫 번째 질문에서 할 수없는 제안이었습니다. 사실입니까? 그렇다면 이유를 아는 것이 매우 흥미로울 것입니다.

이 작업을 수행 할 수 있습니까? 어떤 사람이 주석을 달았습니다 (어떤 이유로 제거되었거나 틀렸을 수도 있습니다). 가능한 한 그렇지만 이 동적 라이브러리에 필요하기 때문에 libc의 동적 링크 버전이 존재해야합니다 (예 : 동적 libm에는 동적 libc (?)가 필요합니다.

이것은 괜찮습니다. GCC에게 정적 또는 동적으로 libc의 링크를 지정하는 방법을 알지 못합니다. 나는 이것을 어떻게 하는가? (나는 몇 가지 시도를했고, 어떤 것은 질문의 뒷부분에 표시되어있다)? 아니면 내가 원하는 것을 할 수있는 다른 방법이 있습니까?

다음과 같이 우리는 첫째, 단순히 GCC TEST.C의 -lm을 실행하여, 모든 동적으로 연결되어 있음을 볼 수 : 동적 남아 libc의 허용하면서

$ 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) 

는 만 libm의 정적 연결하려면 우리가 할 수있는 할 (Z 보손으로 상기 질문 중 하나 지적) :

$ 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의 연결 및 동적 libm의 수, 작동하지 않는 것 :

$ 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; 
} 

편집 :

Static link of shared library function in gcc

어느 :이 질문에 제안 나는 또한, statifier과 순백을 시도했습니다

공장.

+0

해결하려는 문제는 무엇입니까? 더 높은 수준에서 말입니다. "정적으로 링크하고 싶습니다." 아마도 우리는 그 문제를 해결할 수 있습니다. –

+0

'libm'은'libc'에 링크합니다 - 문제의 일부일 수도 있습니다 ('ldd/usr/lib64/libm.so'를보십시오). –

+0

@ 존 Zwinck, 그것은 사소한 일이 아니지만, 일부 특수한 상황에서 인텔 MPX에 대해 ROP 기반 익스플로잇이 가능하다는 것을 보여주고 싶지만, libmpx (동적 링크 형식으로 존재하며 소스 코드가 없습니다 , 내가 아는 한) 동적으로 링크되고 libc는 정적으로 링크됩니다. 그러나 이것이 가능하지 않다면 어떤 이유에서인지를 아는 것이 흥미로울 것이고 나는 다른 접근법을 찾아 볼 것입니다. – AttributedTensorField

답변

16

기본적으로, 첫 번째 방법은이 작업을 수행하는 올바른 방법은 다음과 같습니다

gcc test.c libc.a -lm 

GCC는 암시 같은 것이 개념 상 살펴 보겠습니다 라이브러리에 추가 한 후 :

gcc crt1.o test.c libc.a -lm -lc -lgcc -lc 
그래서

것을 의미 crt1.o 또는 test.c이 호출하는 libc 함수는 libc.a에서 가져와 정적으로 연결되지만 이라는 함수는에서이라는 함수 만 호출됩니다.또는 libgcc은 동적으로 링크됩니다 (그러나 libm이 이미 가져온 것을 호출하면 정적 함수가 다시 사용됩니다).

링커는 항상 가장 왼쪽의 파일/라이브러리에서 시작하여 오른쪽으로 작동합니다. 결코 되돌아 가지 않습니다. .c.o 파일은 무조건 연결되지만 .a 파일과 -l 옵션은 이미 참조되었지만 아직 정의되지 않은 기능을 찾는 데에만 사용됩니다. 따라서 왼쪽에있는 라이브러리는 무의미합니다 (-lc은 에 의존하고 -lgcc에 의존하고 -lgcc-lc에 의존하므로 -lc은 두 번 나타나야합니다). 링크 순서가 중요합니다. 의 STT_GNU_IFUNC 것은 함수의 여러 버전을 포함 할 수있는 똑똑한 기능은 다음과 같습니다

불행하게도, 당신은 (또는 오히려 strcmp 들어있는 libc의) strcmp의 버그가 무엇인지에 의해 좌절 된 것으로 표시 사용 가능한 하드웨어를 기반으로 런타임에 가장 최적의 선택이 가능합니다. 확실하지 않지만이 기능은 PIE (Position Independent Executable) 또는 공유 라이브러리 빌드에서만 사용할 수있는 것처럼 보입니다. 그 정적 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 파일을 그대로 명령 사용법은 약간 다르므로이 예제는 .a 파일에서 .o 파일을 추출한 다음 명시 적으로 연결합니다.

+0

환상적! 정확히 내가 찾고/바라는 대답. 나는 실제로 (검색하는 동안)이 버그와 관련된 게시물을 발견했지만 게시물이 2 ~ 3 년이되어서이를 기각했다. – AttributedTensorField

+0

제쳐두고 (질문에 대한 답변은 매우 좋았습니다.) 불행히도 저는 MPX 라이브러리 (libmpx)를 사용하여 "a.out : 공유 라이브러리를로드하는 동안 오류가 발생했습니다 : RTLD_NEXT 코드를 동적으로로드하지 않았습니다."라는 메시지가 나타납니다.그러나 나는 그것으로 더 많이 볼 것이다. – AttributedTensorField

+0

이것은 잘 테스트 된 배열이 아니라고 말하는 것이 안전하다고 생각합니다. 버그가 많을 수 있습니다. 어쩌면 쇼 스토퍼 일 수도 있습니다. – ams

3

ams의 답을 바탕으로 수행했습니다.

mystrcmp.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 -m elf_x86_64 -o 수학 crt1.o crti.o test.o mystrcmp. libc.a libgcc_eh.a libc.a libm.so -dynamic-linker /lib64/ld-linux-x86-64.so.2 crtn.o

이 링크가 올바르게 실행됩니다. 그러나 ldd 그 동적 libm 동적 libc을 필요로 나타납니다

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) 

보여줍니다. 사실, 그 보고서

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) 

그래서 당신의 libc에 대한 종속성없이 libm의 컴파일을 관리하지 않는뿐만 아니라 libc.so 연결하지 않고 libm.so 링크를하는 것은 불가능

libm.so

LDD를 보여 쉽습니다.

+0

libc 전에 실제로 필요한 모든 .o 파일을 실제로 가져 왔는지 궁금합니다. 그래서 요청 받았다. – Xennex81

관련 문제