답변:
dlopen
시스템 호출이 아니며 libdl 라이브러리 의 라이브러리 함수입니다 . 에 시스템 호출 만 표시됩니다 strace
.
Linux 및 기타 여러 플랫폼 (특히 실행 파일에 ELF 형식을 사용하는 플랫폼)에서는 dlopen
대상 라이브러리를 열고를 사용하여 open()
메모리에 매핑 하여 구현됩니다 mmap()
. mmap()
여기서 중요한 부분입니다. 라이브러리를 프로세스의 주소 공간에 통합하여 CPU가 코드를 실행할 수 있습니다. 그러나 당신은 그것을 open()
할 수 mmap()
있기 전에 파일에 있어야 합니다!
ld-linux
하고 커널이 execve
시스템 호출의 일부로 매핑 한다는 것이 적절하다고 생각합니다 .
dlopen은 공유 라이브러리와는 아무런 관련이 없습니다. 공유 객체를로드하는 방법에는 두 가지가 있습니다.
main
함수가 호출 되기 직전에 동적 런타임 링커 (ld.so)가 호출 되고 응용 프로그램이 라이브러리의 기능을 찾을 수 있도록 응용 프로그램의 프로세스 공간을 설정합니다. 여기에는 open()
윤활유를 바르고 mmap()
룩업 테이블을 설정하는 것이 포함됩니다 .libdl
(첫 번째 방법을 사용하여) dlopen()
and를 호출 할 수 있습니다.dlsym()
기능. dlopen을 사용하면 라이브러리에 대한 핸들을 얻습니다. 그런 다음 dlsym과 함께 사용하여 특정 함수에 대한 함수 포인터를받을 수 있습니다. 이 방법은 첫 번째 방법보다 프로그래머에게 훨씬 더 복잡합니다 (링커가 자동으로 설정하는 대신 수동으로 설정을 수행해야하기 때문에). -time은 첫 번째 방법에서 얻을 때 올바른 인수 유형으로 함수를 호출하고 있는지 확인하지만 이점은 런타임에로드 할 공유 객체 (또는로드 여부)를 결정할 수 있다는 것입니다. 플러그인 유형 기능을위한 인터페이스입니다. 마지막으로, dlopen 인터페이스는 역학 링커의 정확한 구현에 의존하기 때문에 다른 방법보다 이식성이 떨어집니다.libltdl
이 차이점을 추상화하려고 시도합니다.ltrace -S
mmap
glibc 2.23에서 사용되는 최소 예제 분석
glibc 2.23, Ubuntu 16.04 latrace -S
에서는 다음 dlopen
과 함께 사용되는 최소 프로그램 에서 실행 됩니다 .
ltrace -S ./dlopen.out
보여줍니다 :
dlopen("libcirosantilli_ab.so", 1 <unfinished ...>
SYS_open("./x86_64/libcirosantilli_ab.so", 524288, 06267650550) = -2
SYS_open("./libcirosantilli_ab.so", 524288, 06267650550) = 3
SYS_read(3, "\177ELF\002\001\001", 832) = 832
SYS_brk(0) = 0x244c000
SYS_brk(0x246d000) = 0x246d000
SYS_fstat(3, 0x7fff42f9ce30) = 0
SYS_getcwd("/home/ciro/bak/git/cpp-cheat"..., 128) = 54
SYS_mmap(0, 0x201028, 5, 2050) = 0x7f1c323fe000
SYS_mprotect(0x7f1c323ff000, 2093056, 0) = 0
SYS_mmap(0x7f1c325fe000, 8192, 3, 2066) = 0x7f1c325fe000
SYS_close(3) = 0
SYS_mprotect(0x7f1c325fe000, 4096, 1) = 0
그래서 우리는 즉시 + 를 dlopen
호출 하는 것을 봅니다 .open
mmap
이 멋진 ltrace
툴은 라이브러리 호출과 시스템 호출을 모두 추적하므로이 경우 진행중인 작업을 검사하는 데 적합합니다.
더 자세히 분석 open
하면 파일 설명자를 반환합니다 3
(stdin, out 및 err 다음에 비어 있음).
read
그런 다음 해당 파일 디스크립터를 사용하지만 TODO mmap
의 인수가 4로 제한되는 이유 는 5 번째 인수이므로 어떤 fd가 사용되었는지 알 수 없습니다 . strace
예상 한대로 확인 3
하고 우주의 순서가 복원됩니다.
용감한 영혼은 또한 glibc 코드로 모험을 할 수 있지만, 나는 mmap
빨리 grep을 찾을 수 없었고 게으르다.
GitHub에 빌드 상용구를 사용하여이 최소 예제로 테스트했습니다 .
strace
시스템 호출에 관한보고 (즉, 커널에 의해 직접 구현 된 함수). 동적 라이브러리는 커널 기능이 아닙니다. dlopen
커널이 아닌 C 라이브러리의 일부입니다. 라이브러리 파일을 읽기 위해 dlopen
will 호출 open
(시스템 호출)을 구현하여 읽을 수 있습니다.
ltrace
.
ltrace -S
그것 또한 쇼의 콜로이를 분석하는 완벽 : unix.stackexchange.com/a/462710/32558