약한 심볼을 덮어쓰기 위해 정적 라이브러리에서 gcc 링크 강한 심볼을 만드는 방법?
내 문제는 다음과 같이 요약할 수 있습니다.
bar.c:
#include <stdio.h>
void bar() {
printf("bar\n");
}
main.c:
#include <stdio.h>
void __attribute__((weak)) bar() {
printf("foo\n");
}
int main() {
bar();
return 0;
}
파일 만들기:
all:
gcc -c bar.c
ar -rc libbar.a bar.o
gcc main.c -L. -lbar
출력:
$ ./a.out
foo
따라서 main.c의 weak symbol bar는 정적 라이브러리 libbar.a의 main.c에 연결되어 있기 때문에 bar.c의 weak symbol bar가 bar.c의 strong symbol에 덮어쓰지 않습니다.
gcc에게 libbar.a에서 weak symbol을 main.c에서 weak symbol을 덮어쓰도록 하려면 어떻게 해야 합니까?
나는 max.haredoom이 주는 대답(그리고 그것이 받아들여졌다는 것)에 어리둥절합니다.답은 공유 라이브러리와 동적 링크를 다루는 반면, 정적 라이브러리를 이용한 정적 링크의 행동에 대한 질문은 명확했습니다.오해의 소지가 있다고 생각합니다.
정적 라이브러리를 링크할 때,ld
기본적으로 약한/강한 기호는 신경 쓰지 않습니다. 정의되지 않은 기호를 첫 번째 encount 기호로 간단히 해결합니다. 따라서 명령줄에서 정적 라이브러리의 순서가 중요합니다.
그러나 이 기본 동작은 다음을 사용하여 변경할 수 있습니다.--whole-archive
선택.Makefile의 마지막 단계를 다음과 같이 다시 작성하는 경우:
gcc main.c -L. -Wl,--whole-archive -lbar -Wl,--no-whole-archive
그러면 다음을 보게 됩니다.
$ ./a.out
bar
한마디로 말하면,--whole-archive
링크기가 모든 기호(이미 확인된 기호 포함)를 검색하도록 합니다.(우리의 경우처럼) 이미 약한 기호로 해결된 강한 기호가 있다면, 강한 기호가 약한 기호를 지배할 것입니다.
또한 Eli Bendersky의 정적 라이브러리와 링크 프로세스 "정적 링크에서 라이브러리 순서"에 대한 훌륭한 게시물과 이 SO 질문을 참조하십시오.
일반적으로 말하면: 고객의 요구 사항에 약한 구현을 적용하지 않는 경우main
, 링커는 실행 시에 최종적으로 해결할 것입니다.하지만 당신이 그것을 실행한다면,main.c
, 강한 경계를 가진 상태로만 덮어쓸 수 있습니다 (bar.c
) 이 정적 링크를 연결할 때.
https://bottomupcs.com/ch09s05.html 을 읽어보세요. 이 주제에 대한 흥미로운 내용들이 많이 포함되어 있습니다.
제가 직접 테스트를 해봤습니다.
바의
#include <stdio.h>
void bar()
{
puts("bar.c: i'm the strong bar()");
}
baz.c
#include <stdio.h>
void __attribute__((weak)) bar()
{
puts("baz.c: i'm the weak bar()");
}
본전의
#include <stdio.h>
#ifdef V2
void __attribute__((weak)) bar()
{
puts("main: i'm the build in weak bar()");
}
#else
void __attribute__((weak)) bar();
#endif
int main()
{
bar();
return 0;
}
내 만들기 파일:
all:
gcc -c -o bar.o bar.c
gcc -shared -fPIC -o libbar.so bar.o
gcc -c -o baz.o baz.c
gcc -shared -fPIC -o libbaz.so baz.o
gcc -o main1 main.c -L. -lbar -lbaz
gcc -o main2 main.c -L. -lbaz -lbar
LD_LIBRARY_PATH=. ./main1 # => bar.c
LD_LIBRARY_PATH=. ./main2 # => baz.c
LD_LIBRARY_PATH=. LD_PRELOAD=libbaz.so ./main1 # => baz.c (!!)
LD_LIBRARY_PATH=. LD_PRELOAD=libbaz.so ./main2 # => baz.c
gcc -o main3 main.c bar.o baz.o
gcc -o main4 main.c baz.o bar.o
./main3 # => bar.c
./main4 # => bar.c
gcc -DV2 -o main5 main.c -L. -lbar -lbaz
gcc -DV2 -o main6 main.c -L. -lbaz -lbar
LD_LIBRARY_PATH=. ./main5 # => main's implementation
LD_LIBRARY_PATH=. ./main6 # => main's implementation
gcc -DV2 -o main7 main.c -L. -lbar -lbaz
gcc -DV2 -o main8 main.c -L. -lbaz -lbar
LD_LIBRARY_PATH=. LD_PRELOAD=libbaz.so ./main7 # => main's implementation
LD_LIBRARY_PATH=. LD_PRELOAD=libbaz.so ./main8 # => main's implementation
gcc -DV2 -o main9 main.c -L. -lbar -lbaz
gcc -DV2 -o main10 main.c -L. -lbaz -lbar
LD_LIBRARY_PATH=. LD_PRELOAD=libbar.so ./main9 # => main's implementation
LD_LIBRARY_PATH=. LD_PRELOAD=libbar.so ./main10 # => main's implementation
gcc -c bar.c
gcc -c baz.c
gcc -o main11 main.c bar.o baz.o
gcc -o main12 main.c baz.o bar.o
./main11 # => bar.c
./main12 # => bar.c
gcc -o main13 -DV2 main.c bar.o baz.o
gcc -o main14 -DV2 main.c baz.o bar.o
./main13 # => bar.c
./main14 # => bar.c
main1과 main2를 보세요.만약 당신이 어떤 약한 실행할 수 있습니다.main.c
하지만 약한 것은 도서관에, 강한 것은 또 다른 lib.에 보관하세요. 만약 강한 lib가 강력한 구현을 정의한다면 약한 것을 무시할 수 있을 것입니다.bar()
.
약한 구현을 다른 라이브러리로 분리해야 합니다.
본론으로만 신고하세요.
언급URL : https://stackoverflow.com/questions/13089166/how-to-make-gcc-link-strong-symbol-in-static-library-to-overwrite-weak-symbol
'programing' 카테고리의 다른 글
부트스트랩 3.0 팝오버 및 툴팁 (0) | 2023.10.02 |
---|---|
.NET에서 개체를 UTF-8 XML로 직렬화 (0) | 2023.10.02 |
주피터 노트북에서 3D 그림을 대화식으로 만들기 (0) | 2023.10.02 |
Wordpress SQL 사용자 지정 게시물 유형 및 메타 삭제 (0) | 2023.10.02 |
워드프레스에서 $_POST 사용방법 (0) | 2023.10.02 |