저는 프로세스나 스레드가 터미널 신호(예: SIGSEGV, SIGABRT)를 수신할 때 추적을 내보내도록 Linux에서 실행되는 애플리케이션을 향상시키고 있습니다.
backtrace(3)
코드는 backtrace_symbols(3)
, 를 사용하여 잘 작동하며 역추적 dladdr(3)
에 abi::__cxa_demangle
유용한 정보를 생성합니다 .
addr2line
그 외에도 소스 파일 이름과 줄 번호를 생성하려고 할 때 제공된 주소를 사용하여 실행 파일을 보내면 잘 작동하는 것을 발견했지만 최근에는 기호가 공유 객체에 있는 한 backtrace(3)
생성하기 쉽습니다 ??:0
. backtrace
친구가 신고한 주소가 ASLR의 영향을 받은 것 같습니다 . 이 문제는 내 스택 추적의 대부분(전부는 아니지만)에 영향을 미치며 현재 forking 의 가치를 감소시키고 있습니다 addr2line
.
문제를 해결하고 파일 및 줄 번호를 얻는 방법에 대한 인터넷 결과가 드물어지기 시작했습니다. 그러나 나는 최근에 다음 문제를 해결하기 위해 메모리 매핑이 어떻게 작동하는지 충분히 배웠습니다.
backtrace_symbols(3)
공유 개체에 이 주소와 오프셋을 추가하고 이를 보낼 때 제공된 기호를 찾기 위해 이 공유 개체와 함께 사용할 수 있는 공유 개체에 대한 경로가 포함된 문자열을 제공합니다dladdr(3)
. 파일과 줄 번호가 올바르게 생성되었습니다.dli_fname
nm
backtrace_symbols
addr2line -e <sharedobjectpath>
/proc/<pid>/maps
공유 개체 경로에서 매핑된 주소를 조회r-xp
하고 보고된 주소에서 해당 값을 빼면backtrace(3)
위의 공유 개체와 정확히 동일한 주소를 얻을 수 있습니다.- 공유 객체 맵 주소를 직접 가져오면(아직 테스트하지는 않았지만 직감적으로)
dladdr1(3)
액세스를 건너뛸 수 있을 수도 있습니다/proc/<pid>/maps
.
addr2line
어쨌든 여기서는 파일과 줄 번호를 가져오기 위해 분기해야 하는 것 같습니다. 이는 약간 고통스럽고(수백 밀리초가 소요됨) libbfd
내 응용 프로그램에 종속성으로 도입하지 않고 필요한 것 같습니다.
고쳐 쓰다:자세히 살펴보지 않았는데 에서 찾은 주소가 /proc/<pid>/maps
의 값과 동일하다는 것을 알게 되었습니다. 그게 다야. 전혀 위를 쳐다볼 필요가 없습니다.dli_fbase
dladdr(3)
/proc/<pid>/maps
이를 수행하는 더 깨끗하고 직접적인 방법이 있습니까? 세 번째 글머리 기호로 인해 addr2line
. (편집하다: 주소를 알려주실 수 있나요? 제 언급은 무시하세요 /proc/<pid>/maps
. ) 두 번째 글머리 기호는 이미 필요한 포크를 얻기 위해 읽을 수 있음을 보여 주며 /proc/<pid>/maps
addr2line
, 다소 큰 메모리 매핑 출력을 스캔하는 것은 많은 작업이지만 후속 호출보다 확실히 빠릅니다 . 세 번째 글머리 기호는 실행 불가능한 것으로 판명됨) 내 프로그램에서 액세스하는 것과 관련된 보안/액세스/보안 문제가 있습니까 달리기 /proc/<pid>/maps
?는 어때요addr2line
?