제목이 분명합니다. dl_open
등으로 라이브러리를로드 할 수 있습니다.공유 라이브러리에있는 함수의 서명을 프로그램 적으로 얻을 수 있습니까?
하지만 어떻게 함수의 서명을 얻을 수 있습니까?
제목이 분명합니다. dl_open
등으로 라이브러리를로드 할 수 있습니다.공유 라이브러리에있는 함수의 서명을 프로그램 적으로 얻을 수 있습니까?
하지만 어떻게 함수의 서명을 얻을 수 있습니까?
아니요. 불가능합니다. 함수의 서명은 런타임시 아무 것도 의미하지 않으며 컴파일러가 프로그램을 검증하기 위해 컴파일 할 때 유용한 정보입니다.
이 진술이 정확하지 않다고 생각합니다. 근본적으로 불가능하다고 말하는 것입니다. 서명을 복구하기 위해 할 수있는 많은 것들이 있습니다. 호출 규칙을 살펴볼 수 있으며 오염 분석을 사용할 수있는 경우 다른 알려진 서명의 인수를 추적하고 유형을 원하는 함수로 되돌릴 수 있습니다. –
수 없습니다. 라이브러리가 헤더에 공개 API를 게시하거나 다른 방법으로 서명을 알아야합니다.
하위 수준의 함수 매개 변수는 스택 프레임의 스택 인수 개수와 해석 방법에 따라 달라집니다. 따라서 일단 함수가 객체 코드로 컴파일되면 그런 서명을 얻을 수 없습니다. 한 가지 가능한 방법은 코드를 분해하고 함수가 매개 변수 인 경우 숫자를 알기 위해 작동하는 방법을 읽는 것입니다. 그러나 유형을 결정하는 것은 어렵거나 불가능합니다. 즉, 불가능합니다.
이 정보는 제공되지 않습니다. 심지어 디버거 알고 :
$ 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)
적어도 디버거는 함수임을 알고 있습니다. int(). –
@Je Rog,하지만'memcpy'에서 볼 수 있듯이 리턴 타입의 기본 규칙을 적용하기 때문에 그다지 도움이되지 않습니다. –
@Jens Gustedt, 디버거가 처음에 함수라는 것을 어떻게 알았습니까? –
이 답변은 일반적으로 대답 할 수 없습니다. 기술적으로 완전한 디버깅 정보 (코드가 여전히 최적화 된 릴리스 버전 일 수 있음)로 실행 파일을 컴파일 한 경우 실행 파일에는 이진의 일종의 반사율을 제공하는 추가 섹션이 포함됩니다. * 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)에당신이
나노 mylibrary.so (라이브러리 C++에 대한) "나노"와 "C++ filt을"의 조합을 사용할 수 있습니다 | C++ filt을
또는
나노 mylibrary.a | C++ filt
"nm"은 mangled 형식을 제공하고 "C++ filt"는 사람이 읽을 수있는 형식으로 지정하려고 시도합니다. nm의 몇 가지 옵션을 사용하여 결과를 필터링 할 수 있습니다 (특히 라이브러리가 큰 경우 (또는 특정 항목을 찾기 위해 최종 출력을 "grep"할 수 있음)
정보 mangling에 대한 Wikipedia 기사는 유익합니다 C와 C++에 대한 객체 코드 이름으로 인코딩 된 정보와 컴파일러에 따라 다양한 정보를 볼 수 있습니다. http://en.wikipedia.org/wiki/Name_mangling – HostileFork
@Hostile Fork, ** single **'.so ', 다른 이름의 manglings을 가질 수 있습니까? –
Wikipedia 기사에서 언급했듯이 C에서의 mangling은 Windows 규칙을 지원하기위한 것이며'.so' 파일에는 나타나지 않습니다. C++의 경우, 동일한 함수 이름을 가진 여러 manglings들이 하나의'.so'에 나타나서 오버로딩의 언어 기능을 지원합니다. http://en.wikipedia.org/wiki/Function_overloading – HostileFork