개발 중에 시스템 라이브러리에 디버깅 기호를 연결하는 모범 사례는 무엇입니까?

개발 중에 시스템 라이브러리에 디버깅 기호를 연결하는 모범 사례는 무엇입니까?

나는 시스템 패키지의 디버그 버전을 설치하는 것이 매우 편리한 프로젝트 단계에 있습니다. 적어도 우분투에서는 라이브러리에 디버깅 기호를 추가하는 것이 식은 죽 먹기입니다. 거의 모든 패키지에는 -dbg유용한 역추적에 필요한 모든 기호를 제공하는 변형이 있습니다.

하지만 저는 현재 Arch Linux를 사용하고 있습니다.일반적인 합의해결 방법은 사용자 makepkg.conf파일을 편집하고 디버그 플래그를 (C|CXX|CPP|LD)FLAGS. 글쎄요, 제 생각에는 "소스 기반 배포"에는 충분히 공평하지만 금방 지루해집니다.

그렇다면 시스템 패키지에 디버깅 기호를 첨부하는 가장 좋은 방법은 무엇입니까? 다른 패키징업체는 어떻게 하나요?

strip디버깅 기호를 추출하여 외부 파일에 저장하는 것이 가능하다는 것을 본 것 같습니다 . gdb시스템 애플리케이션이 파일을 찾느라 애쓰지 않고도 역추적 중에 이러한 기호 파일을 선택할 수 있습니까 ? 포장업자의 관점에서 이것이 어떻게 작동합니까?

이것은 단지 생각일 뿐인데, chroot개발 환경을 조성하는 것이 좋은 생각일까요? (패키지의 디버그 버전과 릴리스 버전 사이에 ABI 비호환성이 있는 문제가 있습니다. 이는 약간 고통스럽습니다. 공유 라이브러리에 연결된 모든 항목도 기호 누락에 대해 불평하므로 최적화된 버전으로 되돌립니다. )

답변1

배포하는 경우원천패키지에서 (autotools) 사양은 기본 컴파일 디버깅 기호입니다.

나는 한때 주류였던 Linux 배포판도 바이너리에 보관했다고 생각합니다. 디버깅 기호를 제거하면 소프트웨어가 "최적화"된다는 오해가 있습니다. 그러나 실제로는 그렇지 않습니다. 디버깅 기호를 포함함으로써 발생하는 유일한 차이점은 파일이 디스크에서 차지하는 공간입니다. 일반적인 사용 중에는 메모리에 로드되지 않으므로 메모리 사용량에는 영향을 미치지 않습니다. 따라서 다른 것에도 영향을 미치지 않습니다. 제거된 바이너리와 제거되지 않은 바이너리를 분석해 보세요. 그들은 동일합니다.

배포 패키지에서 분할하는 목적은 전체 설치 크기가 3.8GB가 아닌 2.5GB가 되도록 각 패키지의 크기를 줄이는 것입니다. 공식 저장소에 포함하기 위해 패키지를 선택한 경우 배포판은 해당 패키지를 소스에서 패키지합니다. 그들은 미리 만들어진 패키지를 사용하지 않을 것이므로 지금 이 작업을 수행(별도의 디버그 패키지 생성)하는 것은 그 점에서 영향을 미치지 않습니다.

다양한 배포판에 대해 독립적으로 라이브러리 바이너리 패키지를 배포하는 경우 디버깅 기호가 컴파일되는지 여부는 아무도 신경 쓰지 않으며 라이브러리를 사용하여 프로그래밍하는 대부분의 사람들은 이를 필요로 합니다. 어떤 이상한 이유로 괴로워하는 소수의 사람들은 어쨌든 쉽게 제거됩니다.

따라서 프로그래머이자 Linux 사용자로서 내 의견을 듣고 싶다면 적어도 지금은 그대로 두십시오. "조기 최적화"에 대한 명백한 초점, 특히 실제 최적화가 아닌 조기 최적화는 보기에 좋지 않습니다. 즉, 귀하의 질문에 대한 문자 그대로의 대답은 다음과 같습니다: "모범 사례개발 중에 시스템 라이브러리에 디버깅 기호를 첨부하는 방법은 다음과 같습니다.그들을 컴파일".

즉, 나는 눈치챘다이 페이지 WRT .deb 패키지옛날에는 내가 내 믿음을 입증하려고 할 때 그것들이 항상 포함되었습니다. 태그에 dpkg를 포함시켰으므로 효과가 있을 수 있습니다.

답변2

빌드 옵션에 다음을 추가합니다 OPTIONS+=(debug !strip)( ) ./etc/makepkg.confDEBUG_CFLAGS="-g -fvar-tracking-assignments"

이들 중 어느 것도 비활성화되지 않습니다.어느최적화(https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html). 디버그 기호를 사용하여 최적화된 빌드를 얻을 수 있습니다.아니요많은 사람들이 "디버그 빌드"에 대해 이야기할 때 그 의미는 무엇입니까? 이렇게 하려면 -O0또는 -Og("디버깅 최적화")를 활성화할 수도 있습니다.

디버그 형식은 레지스터에 있는 변수를 메모리에 넘치지 않고 추적할 수 없기 때문에 일반적 으로 gdb로 디버깅할 때 print some_local제공됩니다 . (optimized out)물론 완벽한 디버그 형식이라도 변수가 실제로 최적화되어 있고 C 소스 코드와 일치하는 값을 보유하는 레지스터나 메모리가 없는 상황을 실제로 수정할 수는 없습니다. 여전히 (상당히) 안정적으로 역추적을 얻을 수 있고 인라인되지 않은 함수에 함수 인수를 전달할 수 있습니다.


https://wiki.archlinux.org/index.php/Debug__-_Getting_Traces이는 현재 기호 정보 (debug strip)를 .somepkg-debug/usr/lib/debugsomepkg-dbg

물론 이 디버그 패키지는 기존 바이너리 패키지와 함께 사용할 수 없습니다. 약간의 차이로 인해 잘못된 디버그 정보가 발생할 수 있기 때문입니다.

불행하게도 사전 빌드된 바이너리 패키지용 디버그 패키지를 배포하기 위한 저장소/패키지 시스템은 없습니다. 따라서 디버그 기호를 원하는 패키지를 로컬로 컴파일해야 합니다.

장점으로는 -march=native특히 시스템에 맞게 바이너리를 최적화할 수 있는 좋은 기회입니다. 예를 들어 보다 효율적인 가변 카운트 시프트 명령, 하드웨어 popcnt및 AVX/AVX2/FMA/AVX512 벡터 명령을 위해 BMI2와 같이 CPU에서 지원하는 모든 기능을 활성화합니다 . -march=native또한 설정 -mtune=native,이것은 좋다.

라이브러리와 동일한 파일에 디버깅 정보를 보관하는 데 따른 성능 오버헤드는 무시할 수 있습니다. 전체 콘텐츠가 /usr/lib/libc.so.6RAM에 로드되지 않고 필요한 페이지만 매핑됩니다. 디버그 정보는 바이너리 파일로 함께 그룹화되므로 이러한 페이지는 디스크에 그대로 남아 있을 수 있습니다.

관련 정보