2011-07-30 4 views
6

제목이 분명합니다. dl_open 등으로 라이브러리를로드 할 수 있습니다.공유 라이브러리에있는 함수의 서명을 프로그램 적으로 얻을 수 있습니까?

하지만 어떻게 함수의 서명을 얻을 수 있습니까?

+0

정보 mangling에 대한 Wikipedia 기사는 유익합니다 C와 C++에 대한 객체 코드 이름으로 인코딩 된 정보와 컴파일러에 따라 다양한 정보를 볼 수 있습니다. http://en.wikipedia.org/wiki/Name_mangling – HostileFork

+0

@Hostile Fork, ** single **'.so ', 다른 이름의 manglings을 가질 수 있습니까? –

+0

Wikipedia 기사에서 언급했듯이 C에서의 mangling은 Windows 규칙을 지원하기위한 것이며'.so' 파일에는 나타나지 않습니다. C++의 경우, 동일한 함수 이름을 가진 여러 manglings들이 하나의'.so'에 나타나서 오버로딩의 언어 기능을 지원합니다. http://en.wikipedia.org/wiki/Function_overloading – HostileFork

답변

4

아니요. 불가능합니다. 함수의 서명은 런타임시 아무 것도 의미하지 않으며 컴파일러가 프로그램을 검증하기 위해 컴파일 할 때 유용한 정보입니다.

+0

이 진술이 정확하지 않다고 생각합니다. 근본적으로 불가능하다고 말하는 것입니다. 서명을 복구하기 위해 할 수있는 많은 것들이 있습니다. 호출 규칙을 살펴볼 수 있으며 오염 분석을 사용할 수있는 경우 다른 알려진 서명의 인수를 추적하고 유형을 원하는 함수로 되돌릴 수 있습니다. –

1

수 없습니다. 라이브러리가 헤더에 공개 API를 게시하거나 다른 방법으로 서명을 알아야합니다.

0

하위 수준의 함수 매개 변수는 스택 프레임의 스택 인수 개수와 해석 방법에 따라 달라집니다. 따라서 일단 함수가 객체 코드로 컴파일되면 그런 서명을 얻을 수 없습니다. 한 가지 가능한 방법은 코드를 분해하고 함수가 매개 변수 인 경우 숫자를 알기 위해 작동하는 방법을 읽는 것입니다. 그러나 유형을 결정하는 것은 어렵거나 불가능합니다. 즉, 불가능합니다.

0

이 정보는 제공되지 않습니다. 심지어 디버거 알고 :

$ cat foo.c 
#include <stdio.h> 
#include <string.h> 

int main(int argc, char* argv[]) 
{ 
    char foo[10] = { 0 }; 
    char bar[10] = { 0 }; 
    printf("%s\n", "foo"); 
    memcpy(bar, foo, sizeof(foo)); 
    return 0; 
} 

$ gcc -g -o foo foo.c 
$ gdb foo 
Reading symbols from foo...done. 
(gdb) b main 
Breakpoint 1 at 0x4005f3: file foo.c, line 5. 
(gdb) r 
Starting program: foo 

Breakpoint 1, main (argc=1, argv=0x7fffffffe3e8) at foo.c:5 
5 { 
(gdb) ptype printf 
type = int() 
(gdb) ptype memcpy 
type = int() 
(gdb) 
+0

적어도 디버거는 함수임을 알고 있습니다. int(). –

+0

@Je Rog,하지만'memcpy'에서 볼 수 있듯이 리턴 타입의 기본 규칙을 적용하기 때문에 그다지 도움이되지 않습니다. –

+0

@Jens Gustedt, 디버거가 처음에 함수라는 것을 어떻게 알았습니까? –

7

이 답변은 일반적으로 대답 할 수 없습니다. 기술적으로 완전한 디버깅 정보 (코드가 여전히 최적화 된 릴리스 버전 일 수 있음)로 실행 파일을 컴파일 한 경우 실행 파일에는 이진의 일종의 반사율을 제공하는 추가 섹션이 포함됩니다. * nix 시스템 (dl_open을 참조 함)에서는 ELF 바이너리의 추가 섹션에서 DWARF 디버깅 데이터를 통해 구현됩니다. 유사은 맥 OS X에서 마하 유니버설 바이너리 작동

윈도우의 PE는하지만 완전히 다른 포맷을 사용하기 때문에 불행하게도 DWARF은 내가 ELF를 구현 내 3D 엔진의 초기 개발 단계에서 실제로 (크로스 플랫폼 이서를 truley하지 않습니다/Windows 용 DWARF 로더, 다양한 모듈에 공통된 형식을 사용할 수 있도록 노력하겠습니다.

로더 또는 디버깅 정보 접근자를 구현하지 않으려면 함수 이름 테이블을 참조하는 일부 표준 기호로 내 보낸 추가 기호를 통해 반사 정보를 포함 할 수 있습니다 , 그들의 서명에 매핑. C 소스 파일의 경우 소스 파일 자체에서 정보를 추출하는 구문 분석기를 작성하는 것이 다소 쉽습니다. C++ OTOH는 올바르게 파싱하기에 너무나 악명이 높습니다. 제대로 작동하려면 완전한 컴파일러가 필요합니다. 이 목적을 위해 GCCXML이 기술적으로 개발되어 객체 바이너리 대신 XML 형식의 AST를 방출합니다. 방출 된 XML은 파싱하기가 훨씬 쉽다.

추출 된 정보에서 링크 된 목록/배열/일종의 소스 파일을 만듭니다. 각 기능을 설명하는 구조. 각 함수의 심볼을 직접 내보내는 대신 함수 포인터를 사용하여 반사 구조의 일부 필드를 초기화하는 경우 정말 멋지고 깨끗한 주석이 달린 내보내기 체계가 있습니다. 기술적으로 바이너리의 spearate 섹션에도이 정보를 넣을 수 있지만, 읽기 전용 데이터 섹션에두면이 작업을 수행 할 수도 있습니다. 당신이 제 3 자 바이너리를 제공하고 그러나 경우


은 - 당신이 거의 끝장 - 그것은 C 소스, 아니 디버깅 정보를 외부 제거 참조하지 않는 모든 기호에서 컴파일 된 최악의 시나리오는 말한다. 당신이 할 수있는 최선의 방법은 함수가 매개 변수를 전달할 수있는 여러 위치에 액세스하는 방식에 대한 몇 가지 이진 분석을 적용하는 것이 었습니다.

이것은 매개 변수의 수와 유형, 이름/의미가 아닌 각 매개 변수 값의 크기 만 알려줍니다. 일부 프로그램 (예 : 맬웨어 분석 또는 보안 감사)을 리버스 엔지니어링 할 때 함수에 전달 된 매개 변수의 유형과 의미를 식별하는 것이 주요 노력 중 하나입니다. 최근에 나는 디버깅 목적으로 리버스해야했던 몇몇 드라이버를 보았고 리눅스 커널 모듈에서 C++ 심볼을 발견했다는 사실에 얼마나 놀랐는 지 믿을 수 없습니다 (Linux 커널에서 C++을 정상적인 방법으로 사용할 수는 없습니다) C++ 이름의 맹 글링은 많은 정보를 제공했기 때문에 안심했다.

리눅스 (또는 Mac)에
0

당신이

나노 mylibrary.so (라이브러리 C++에 대한) "나노"와 "C++ filt을"의 조합을 사용할 수 있습니다 | C++ filt을

또는

나노 mylibrary.a | C++ filt

"nm"은 mangled 형식을 제공하고 "C++ filt"는 사람이 읽을 수있는 형식으로 지정하려고 시도합니다. nm의 몇 가지 옵션을 사용하여 결과를 필터링 할 수 있습니다 (특히 라이브러리가 큰 경우 (또는 특정 항목을 찾기 위해 최종 출력을 "grep"할 수 있음)

관련 문제