리눅스 C 프로그램:함수가 속한 라이브러리를 찾는 방법
런타임에 함수 "printf"가 정의된 위치를 찾고 싶습니다.제가 이걸 어떻게 하죠?저의 첫 번째 시도는 "printf"의 주소를 출력하여 프로세스의 가상 주소 매핑과 비교하는 것이었습니다.
내 프로그램:
#include <stdio.h>
#include <unistd.h>
void main()
{
printf("address of printf is 0x%X\n", printf);
printf("pid is %d\n", getpid());
while (1);
}
출력:
-bash-4.1$ ./a &
[1] 28837
-bash-4.1$ address of printf is 0x4003F8
pid is 28837
하지만 이것은 그 기능이 내 프로그램에 정의되어 있다고 말합니다!
-bash-4.1$ head /proc/28837/maps
00400000-00401000 r-xp 00000000 08:06 6946857 /data2/temp/del/a <<<<<<< Address 0x4003F8 is in my own program?
00600000-00601000 rw-p 00000000 08:06 6946857 /data2/temp/del/a
397ec00000-397ec20000 r-xp 00000000 08:11 55837039 /lib64/ld-2.12.so
397ee1f000-397ee20000 r--p 0001f000 08:11 55837039 /lib64/ld-2.12.so
397ee20000-397ee21000 rw-p 00020000 08:11 55837039 /lib64/ld-2.12.so
397ee21000-397ee22000 rw-p 00000000 00:00 0
397f000000-397f18a000 r-xp 00000000 08:11 55837204 /lib64/libc-2.12.so
397f18a000-397f38a000 ---p 0018a000 08:11 55837204 /lib64/libc-2.12.so
397f38a000-397f38e000 r--p 0018a000 08:11 55837204 /lib64/libc-2.12.so
397f38e000-397f38f000 rw-p 0018e000 08:11 55837204 /lib64/libc-2.12.so
libc에 전화해야하는거 아닌가요?이 "printf" 또는 다른 기능이 어디서 왔는지 어떻게 알 수 있습니까?
관찰하는 주소는 PLT(Procedure Linking Table)에 있습니다.이 메커니즘은 외부(동적으로 연결된) 기호의 위치를 알 수 없는 경우, 이진을 컴파일하고 연결할 때 사용됩니다.
그 목적은 외부 링크가 PLT라는 한 곳에서만 발생하며, 기호에 대한 호출이 발생하는 코드 전체의 모든 곳에서 발생하는 것은 아닙니다.그래서 만약에printf()
라고 하며, 방법은 다음과 같습니다.
main -> printf@PLT -> printf@libc
실행 시 호출하는 함수가 어느 외부 라이브러리에 있는지 쉽게 찾을 수 없습니다. 대개 .dynamic 섹션에서 주소를 가져와 거기로 점프하는 대상(PLT)의 opcode를 파싱한 다음 심볼이 실제로 어디에 있는지 확인하고 마지막으로 /proc/pid/maps를 파싱하여 외부 라이브러리를 가져옵니다.
런타임에 다음을 사용할 수 있습니다.gdb
다음의 경우:
(terminal 1)$ ./a
pid is 16614
address of printf is 0x400450
(terminal 2)$ gdb -p 16614
(...)
Attaching to process 16614
(...)
0x00000000004005a4 in main ()
(gdb)
(gdb) info sym printf
printf in section .text of /lib/x86_64-linux-gnu/libc.so.6
프로그램을 중단하고 싶지 않거나 사용을 꺼리는 경우gdb
, 물어 볼 수도 있습니다.ld.so
몇 가지 디버깅 정보를 출력하는 방법:
(terminal 1)$ LD_DEBUG=bindings LD_DEBUG_OUTPUT=syms ./a
pid is 17180
address of printf is 0x400450
(terminal 2)$ fgrep printf syms.17180
17180: binding file ./a [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `printf' [GLIBC_2.2.5]
포인터는
printf
ed 사용%p
,것은 아니다.%X
:printf("address of printf is 0x%p\n", printf);
정적 libc에 대항하여 컴파일하는 경우
printf
당신의 바이너리에 연결될 것입니다.…으로 정리하면
gcc -fPIC a.c # (older gccs) ... gcc -fno-plt a.c # (gcc 6 and above)
출력:
address of printf is 0x0x7f40acb522a0
안에 있는
7f40acaff000-7f40accc2000 r-xp 00000000 fd:00 100687388 /usr/lib64/libc-2.17.so
여기서 @plt의 의미는 무엇입니까?를 읽어 보십시오.
런타임에 함수 "printf"가 정의된 위치를 찾고 싶습니다.
일반적이고 절대적인 용어로는 아마 그렇게 할 수 없을 것입니다(적어도 쉽지는 않을 것입니다.주어진 함수는 여러 라이브러리에서 정의될 수 있습니다.printf
, 그럴 가능성은 없습니다. C 표준 라이브러리 안에 있기 때문입니다.
Linux 시스템을 처음부터 구축할 경우 빌드 시 모든 라이브러리를 처리하는 것을 꿈꿀 수 있습니다(예: 모든 공유 라이브러리를 구축할 때 모든 공용 이름을 nm(1)로 가져와 일부 데이터베이스에 넣을 수 있음).이것은 현재 실제로 이루어지지는 않았지만, 일부 연구 프로젝트(특히 소프트웨어 유산 및 2019년의 다른 연구 프로젝트)는 그러한 방향으로 진행되고 있습니다.
그건 그렇고, 당신은 몇 개의 도서관이printf
. 예를 들어, 컴퓨터에 GNU glibc와 musl-libc를 모두 설치하는 경우(또는 여러 변형이 있는 경우)glibc
은 두 를 모두 하지 않을 (를 할 수 있습니다.) (,dlopen
둘 다).
아마도 당신은 리눅스 고유의 dladdr(3) 기능을 원할 것입니다.어떤 주어진 주소에서, 그것은 그것을 가지고 있는 공유 객체를 알려줍니다.
함수는 내 프로그램에 정의되어 있습니다.
네. 동적 링크에 대해 더 많이 읽어보세요.특히 Drepper의 공유 라이브러리 작성 방법 논문을 읽어 보십시오.절차 연계표의 목적이 무엇인지 이해합니다.
필요한 동적으로 연결된 라이브러리에 대한 엘프 파일을 구문 분석합니다.그런 다음 필요한 기호를 검색하여 구문 분석할 수 있습니다.
이것은 정적으로 추론할 수 있습니다.실행할 필요 없음:
$ readelf -Ws a.out | grep printf
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.2.5
언급URL : https://stackoverflow.com/questions/52599211/linux-c-program-how-to-find-the-library-to-which-a-function-belongs
'programing' 카테고리의 다른 글
"WSREP: SST 위치를 과거에 설정할 수 없습니다" 오류로 인해 SST 전송을 완료할 수 없습니다. (0) | 2023.10.07 |
---|---|
WordPress Rest API Get All Posts (0) | 2023.10.02 |
절대값 angularjs 표시 (0) | 2023.10.02 |
"npm run dev"와 "npm start"의 차이 (0) | 2023.10.02 |
Javascript/jQuery를 사용하여 이미지가 로드되었는지 확인하려면 어떻게 해야 합니까? (0) | 2023.10.02 |