'-rdynamic'은 정확히 어떤 역할을 하며 언제 필요할까요?
정확히 어떤 일입니까?-rdynamic
(또는--export-dynamic
링커 레벨에서)에 의해 정의되는 심볼 가시성과 어떻게 관련이 있는가?-fvisibility*
플래그 또는 가시성pragma
및__attribute__
s?
위해서--export-dynamic
, ld(1)에 기재된 내용:
... "dlopen"을 사용하여 프로그램에 의해 정의된 기호를 참조할 필요가 있는 동적 개체를 로드하는 경우, 프로그램 자체를 링크할 때 이 옵션을 사용해야 합니다.
내가 이걸 완전히 이해했는지 모르겠어.이 방법 없이는 작동하지 않는 예를 들어 주시겠습니까?-rdynamic
하지만 그걸로요?
편집: 실제로 몇 개의 더미 라이브러리(싱글 파일, 멀티 파일, 다양한 -O 레벨, 기능 간 호출, 숨겨진 기호, 표시 가능)를 컴파일해 보았습니다.-rdynamic
그리고 지금까지 바이트와 동일한 출력(물론 다른 모든 플래그를 일정하게 유지할 때)을 얻었는데, 이는 매우 곤혹스러운 일입니다.
여기 간단한 예시 프로젝트가 있습니다.-rdynamic
.
바
extern void foo(void);
void bar(void)
{
foo();
}
메인
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
void foo(void)
{
puts("Hello world");
}
int main(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
bar();
return 0;
}
파일 만들기
.PHONY: all clean test
LDEXTRAFLAGS ?=
all: prog
bar.o: bar.c
gcc -c -Wall -fpic -o $@ $<
libbar.so: bar.o
gcc -shared -o $@ $<
main.o: main.c
gcc -c -Wall -o $@ $<
prog: main.o | libbar.so
gcc $(LDEXTRAFLAGS) -o $@ $< -L. -lbar -ldl
clean:
rm -f *.o *.so prog
test: prog
./$<
여기서,bar.c
공유 라이브러리가 되다libbar.so
그리고.main.c
이 프로그램이 되다dlopen
s libbar
및 콜bar()
그 도서관에서요. bar()
콜foo()
(외부)bar.c
에 정의되어 있습니다.main.c
.
그래서 없이-rdynamic
:
$ make test
gcc -c -Wall -o main.o main.c
gcc -c -Wall -fpic -o bar.o bar.c
gcc -shared -o libbar.so bar.o
gcc -o prog main.o -L. -lbar -ldl
./prog
./libbar.so: undefined symbol: foo
Makefile:23: recipe for target 'test' failed
그리고...-rdynamic
:
$ make clean
rm -f *.o *.so prog
$ make test LDEXTRAFLAGS=-rdynamic
gcc -c -Wall -o main.o main.c
gcc -c -Wall -fpic -o bar.o bar.c
gcc -shared -o libbar.so bar.o
gcc -rdynamic -o prog main.o -L. -lbar -ldl
./prog
Hello world
-rdynamic
는 실행 파일의 기호를 내보냅니다.이는 주로 Mike Kinghan의 답변에 기재된 시나리오에 대응하지만, 예를 들어 다음과 같이 도움이 됩니다.Glibc의backtrace_symbols()
역추적을 상징합니다.
여기 작은 실험(테스트 프로그램은 여기서 복사)
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
printf ("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
free (strings);
}
/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}
int
main (void)
{
dummy_function ();
return 0;
}
프로그램을 컴파일합니다.gcc main.c
실행 시 다음과 같은 것이 출력됩니다.
Obtained 5 stack frames.
./a.out() [0x4006ca]
./a.out() [0x400761]
./a.out() [0x40076d]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f026597f830]
./a.out() [0x4005f9]
다음으로 컴파일합니다.-rdynamic
,예.gcc -rdynamic main.c
를 다시 실행합니다.
Obtained 5 stack frames.
./a.out(print_trace+0x28) [0x40094a]
./a.out(dummy_function+0x9) [0x4009e1]
./a.out(main+0x9) [0x4009ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f85b23f2830]
./a.out(_start+0x29) [0x400879]
보시다시피, 이제 적절한 스택트레이스를 얻을 수 있습니다!
이제 ELF의 심볼 테이블 엔트리를 조사합니다(readelf --dyn-syms a.out
):
없이.-rdynamic
Symbol table '.dynsym' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace_symbols@GLIBC_2.2.5 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
에는 실행 파일을 포함한 더 많은 기호가 있습니다.
Symbol table '.dynsym' contains 25 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace_symbols@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND backtrace@GLIBC_2.2.5 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
11: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 24 _edata
12: 0000000000601050 0 NOTYPE GLOBAL DEFAULT 24 __data_start
13: 0000000000601068 0 NOTYPE GLOBAL DEFAULT 25 _end
14: 00000000004009d8 12 FUNC GLOBAL DEFAULT 14 dummy_function
15: 0000000000601050 0 NOTYPE WEAK DEFAULT 24 data_start
16: 0000000000400a80 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
17: 0000000000400a00 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
18: 0000000000400850 42 FUNC GLOBAL DEFAULT 14 _start
19: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
20: 00000000004009e4 16 FUNC GLOBAL DEFAULT 14 main
21: 00000000004007a0 0 FUNC GLOBAL DEFAULT 11 _init
22: 0000000000400a70 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
23: 0000000000400a74 0 FUNC GLOBAL DEFAULT 15 _fini
24: 0000000000400922 182 FUNC GLOBAL DEFAULT 14 print_trace
도움이 됐으면 좋겠네요!
Linux 프로그래밍 인터페이스:
42.1.6
기본 프로그램에서 기호 액세스
를 사용한다고 가정합니다.
dlopen()
공유 라이브러리를 동적으로 로드하려면dlsym()
함수의 주소를 얻다)x()
그 도서관에서 전화하고 나서x()
.한다면x()
차례로 함수를 호출하다y()
,그리고나서y()
는 보통 프로그램에 의해 로드된 공유 라이브러리 중 하나에서 검색됩니다.때때로, 그 대신에, 그 대신에,
x()
를 촉구하다y()
(어느 쪽인가 하면)는 메인 스코프)할 수 .다이나믹 링커에서는,이을 링크 」를 사용해 .--export-dynamic
커커: :
$ gcc -Wl,--export-dynamic main.c
(「」를 참조)마찬가지로 다음과 같이 쓸 수 있습니다.
$ gcc -export-dynamic main.c
이러한 옵션 중 하나를 사용하면 동적으로 로드된 라이브러리가 기본 프로그램의 전역 기호에 액세스할 수 있습니다.
gcc -rdynamic
과 " " "gcc -Wl,-E
은 더 됩니다.입니다.
-Wl,--export-dynamic
.
으로 로드된 라이브러리에서만 할 수 , 이 라이브러리는 이이 with with with with with로 열립니다.dlopen()
렸면 츠
하여 rdynamic을 사용하여 합니다.backtrace()
/backtrace_symbols()
Glibc g g g g g g g g g
-rdynamic
수 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
to에 내용은backtrace()
여기서 읽어주세요.
언급URL : https://stackoverflow.com/questions/36692315/what-exactly-does-rdynamic-do-and-when-exactly-is-it-needed
'programing' 카테고리의 다른 글
Windows에서 MySQL 화면 콘솔을 지우려면 어떻게 해야 합니까? (0) | 2022.09.05 |
---|---|
e.getMessage()와 e.getLocalizedMessage()의 차이점 (0) | 2022.09.05 |
MYSQL DATEFF에만 시간 표시 (0) | 2022.09.05 |
open Session()과 get Current Session()의 휴지 상태 (0) | 2022.09.05 |
'blur' 이벤트가 발생할 때 어떤 요소의 포커스가 *to*로 갔는지 어떻게 알 수 있습니까? (0) | 2022.09.05 |