암호:
//a.c I don't use header files as this is just for demo purpose.
extern void function_b(int num);
void function_a(int num) {
function_b(num)
}
//b.c
void function_b(int num) {
...
}
//dll.c
#include <dlfcn.h>
int main() {
void *handle_a;
void *handle_b;
void (*pfunc_a)(int);
...
handle_a = dlopen("./a.so", RTLD_LAZY);
...
pfunc_a = dlsym(handle_a, "function_a");
...
handle_b = dlopen("./b.so", RTLD_GLOBAL);
...
pfunc_a(2020);
...
return 0;
}
dll.c
런타임에 공유 라이브러리를 로드하려고 시도하는 것을 볼 수 있으며 모듈 a
에는 참조가 있고 function_b
모듈 b
에는 정의가 있습니다 function_b
. 공유 라이브러리를 생성하여 프로그램이 실행되기 전에 디스크에 존재하지만 프로그램을 실행하면 기호 조회 오류가 발생한다고 가정 a.so
합니다 b.so
.
./a.so:undefined symbol: function_b
handle_a = dlopen("./a.so", RTLD_LAZY);
하지만 여기서 사용하고 있는 이 코드 줄을 사용하면 RTLD_LAZY
런타임 링커가 기호를 확인하려고 시도하지 않으며 이전에 호출할 function_b
기회를 얻습니다 . 이런 식으로 동적 링커는 b.so의 정의를 사용하여 참조를 수정 합니다.dlopen("b.so", RTLD_GLOBAL)
function_a
a.so
function_b
내 질문은 다음과 같습니다
내 이해가 맞습니까? 동적 링커는 섹션에 있는 function_b의 명령 주소 에 연결/재배치할 수 있도록
.got
또는.got.plt
섹션을 수정해야 합니다 .a.so
.text
b.so
function_b
내 이해가 맞다면 이 경우 동적 링커가 여전히 해결되지 않는 이유는 무엇입니까?
답변1
문제는 동적 링커가 를 확인할 수 없다는 것이 function_b
아니라 두 번째 호출이 dlopen
올바르지 않다는 것입니다.너필요포함 RTLD_LAZY
하거나RTLD_NOW
, 다른 플래그는 이 두 플래그를 보완합니다.
다음 두 값 중 하나를 포함해야 합니다.배너:
b.so
부하를 다음으로 변경하세요.
handle_b = dlopen("./b.so", RTLD_NOW | RTLD_GLOBAL);
작업 프로그램을 생성합니다.
각 호출은 로드된 마지막 라이브러리이기 때문에 와 ; 사이에서 선택 dlopen
해야 합니다 . 위에서 지정했지만(지연 로딩에서는 아무 것도 얻지 못함) 이 경우에도 잘 작동합니다. 이 외에도 다른 플래그를 추가할 수 있습니다. 실행 시 찾을 수 있도록 기호를 전역적으로 사용할 수 있어야 하기 때문입니다 .RTLD_LAZY
RTLD_NOW
b.so
NOW
LAZY
RTLD_GLOBAL
b.so
function_a
function_b
바라보다의 예dlopen(3)
수행해야 할 오류 처리 dlopen
등에 대한 세부 정보를 통해 문제를 밝힙니다.