*.so 파일에서 기능하도록 기능 주소를 매핑하는 방법
역추적 함수는 역추적 집합을 제공합니다. 함수 이름/파일 이름/라인 번호로 매핑하는 방법은 무엇입니까?
for ex:-
backtrace() returned 8 addresses
./libtst.so(myfunc5+0x2b) [0xb7767767]
./libtst.so(fun4+0x4a) [0xb7767831]
./libtst.so(fun3+0x48) [0xb776787f]
./libtst.so(fun2+0x35) [0xb77678ba]
./libtst.so(fun1+0x35) [0xb77678f5]
./a.out() [0x80485b9]
/lib/libc.so.6(__libc_start_main+0xe5) [0xb75e9be5]
./a.out() [0x80484f1]
위 스택에서 파일 이름과 라인 번호를 어떻게 알 수 있습니까?저는 따라 했지만, 운이 없었습니다.제가 틀렸다면 고쳐주세요 :)
for ex:-
./libtst.so(fun2+0x35) [0xb77dc887]
0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result)
result is no way related to function in nm output.
I used addr2line command:-
addr2line -f -e libtst.so 0xb77dc887
??
??:0
그렇다면 런타임이나 런타임 후에 어떻게 해결할 수 있을까요?잘 부탁드립니다...
nm:-
00000574 T _init
00000680 t __do_global_dtors_aux
00000700 t frame_dummy
00000737 t __i686.get_pc_thunk.bx
0000073c T myfunc5
000007e7 T fun4
00000837 T fun3
00000885 T fun2
000008c0 T fun1
00000900 t __do_global_ctors_aux
00000938 T _fini
000009b4 r __FRAME_END__
00001efc d __CTOR_LIST__
00001f00 d __CTOR_END__
00001f04 d __DTOR_LIST__
00001f08 d __DTOR_END__
00001f0c d __JCR_END__
00001f0c d __JCR_LIST__
00001f10 a _DYNAMIC
00001ff4 a _GLOBAL_OFFSET_TABLE_
00002030 d __dso_handle
00002034 A __bss_start
00002034 A _edata
00002034 b completed.5773
00002038 b dtor_idx.5775
0000203c B funptr
00002040 A _end
U backtrace@@GLIBC_2.1
U backtrace_symbols@@GLIBC_2.1
U free@@GLIBC_2.0
U __isoc99_scanf@@GLIBC_2.7
U perror@@GLIBC_2.0
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0
w __cxa_finalize@@GLIBC_2.1.3
w __gmon_start__
w _Jv_RegisterClasses
pmap:-
START SIZE RSS PSS DIRTY SWAP PERM MAPPING
08048000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/a.out
08049000 4K 4K 4K 4K 0K r--p /home/test/libtofun/a.out
0804a000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/a.out
...
b7767000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/libtst.so
b7768000 4K 4K 4K 4K 0K r--p /home/test/libtofun/libtst.so
b7769000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/libtst.so
....
Total: 1688K 376K 82K 72K 0K
쓰기 가능한 128K 프라이빗, 읽기 전용 1560K 프라이빗, 0K 공유 및 376K 참조
libtst.c:-
void myfunc5(void){
int j, nptrs;
#define SIZE 100
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
void fun4(){
char ip;
char *fun = "fun4\0";
printf("Fun name %s\n",fun);
scanf("%c",&ip);
myfunc5();
}
void fun3(){
char *fun = "fun3\0";
printf("Fun name %s\n",fun);
funptr = fun4;
funptr();
}
void fun2(){
char *fun = "fun2\0";
printf("Fun name %s\n",fun);
fun3();
}
void fun1(){
char *fun = "fun1\0";
printf("Fun name %s\n",fun);
fun2();
}
main.c:-
int main(){
char ip;
funptr = &fun1;
scanf("%c",&ip);
funptr();
return 0;
}
더 필요한 정보가 있으면 알려주세요...
섹션 이름과 함께 addr2line에 간격띄우기를 지정합니다.다음과 같이:
addr2line -j .text -e libtst.so 0x26887
편집: 그건 그렇고, 명확하지 않았다면,0x26887
사용자가 제공한 기능:
0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result)
파일을 살펴봤습니다.backtrace.c
그리고.backtracesyms.c
glibc 소스 코드의 파일(git://sourceware.org/git/glibc.git, 은 2482ae433a4249495859343ae1fba408300f2c2e를 커밋합니다.
내가 잘못 읽거나 잘못 이해하지 않았다고 가정하면: 백트레이스() 자체는 런타임에 있는 기호 주소만 제공하는 것처럼 보이는데, 이것은 pmap이나 유사한 것처럼 라이브러리 로드 주소가 필요하다는 것을 의미합니다.그러나 backtrace_symbols()는 주소가 런타임에 프로세스가 아닌 공유 라이브러리 ELF에 상대적이 되도록 사물을 재계산하므로 매우 편리합니다.pmap의 정보가 필요 없다는 뜻입니다.
따라서 -g(또는 -rdynamic)로 컴파일했다면 운이 좋은 것입니다.다음 작업을 수행할 수 있어야 합니다.
$ # get the address in the ELF so using objdump or nm
$ nm libtst.so | grep myfunc
0000073c T myfunc5
$ # get the (hex) address after adding the offset
$ # from the start of the symbol (as provided by backtrace_syms())
$ python -c 'print hex(0x0000073c+0x2b)'
0x767
$ # use addr2line to get the line information, assuming any is available
addr2line -e libtst.so 0x767
또는 gdb 사용:
$ gdb libtst.so
(gdb) info address myfunc
Symbol "myfunc" is at 0x073c in a file compiled without debugging. # (Faked output)
(gdb) info line *(0x073c+0x2b)
Line 27 of "foo.cpp" starts at address 0x767 <myfunc()+21> and ends at 0x769 <something>. # (Faked output)
또한 라이브러리를 벗겼지만 나중에 사용할 수 있도록 디버그 기호를 숨겨둔 경우에는 backtrace_syms()에 의해 ELF 오프셋만 인쇄되고 기호 이름은 인쇄되지 않습니다(따라서 원래 질문에서는 그렇지 않습니다).이 경우 gdb를 사용하는 것이 다른 명령줄 도구를 사용하는 것보다 훨씬 편리합니다.이 작업을 수행했다고 가정하면 다음과 같이 gdb를 호출해야 합니다(예:
$ gdb -s debug/libtst.debug -e libtst.so
그런 다음 ELF 기호 오프셋만 있는지 또는 기호 이름과 오프셋을 더한 값을 사용하는지에 따라 'info line' 및 'info address'를 사용하여 위와 유사한 순서를 수행합니다.
objdump -x --disassemble -l <objfile>
이것은 무엇보다도 C 파일의 줄과 함께 기계 코드의 컴파일된 각 명령어를 덤프해야 합니다.
에 런에임과 함께eu-addr2line
(자동으로 라이브러리를 찾아 오프셋을 계산합니다).
//-------------------------------------
#include <sys/types.h>
#include <unistd.h>
int i;
#define SIZE 100
void *buffer[100];
int nptrs = backtrace(buffer, SIZE);
for (i = 1; i < nptrs; ++i) {
char syscom[1024];
syscom[0] = '\0';
snprintf(syscom, 1024, "eu-addr2line '%p' --pid=%d > /dev/stderr\n", buffer[i], getpid());
if (system(syscom) != 0)
fprintf(stderr, "eu-addr2line failed\n");
}
--debuginfo-path=...
디버깅 파일이 다른 곳에 있는 경우(build-id 등으로 표시됨) 옵션을 선택합니다.
eu-addr2line
에 있습니다.elfutils
배포된 패키지.
언급URL : https://stackoverflow.com/questions/7556045/how-to-map-function-address-to-function-in-so-files
'programing' 카테고리의 다른 글
Mongoose의 배열 스키마로 개체 밀어넣기 (0) | 2023.06.18 |
---|---|
OpenXML을 사용하여 Excel 시트에서 탭 이름을 검색하는 방법 (0) | 2023.06.18 |
j선택한 값 가져오기 라디오 버튼 쿼리 (0) | 2023.06.18 |
Java JDBC - tnsnames.ora를 사용하여 Oracle에 연결하는 방법 (0) | 2023.06.18 |
Intents를 사용하여 한 Android 활동에서 다른 활동으로 개체를 보내는 방법은 무엇입니까? (0) | 2023.06.18 |