programing

리눅스 C 프로그램:함수가 속한 라이브러리를 찾는 방법

javamemo 2023. 10. 2. 10:49
반응형

리눅스 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]
  1. 포인터는printfed 사용%p,것은 아니다.%X:

    printf("address of printf is 0x%p\n", printf);
    
  2. 정적 libc에 대항하여 컴파일하는 경우printf당신의 바이너리에 연결될 것입니다.

  3. …으로 정리하면

    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 glibcmusl-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

반응형