- https://rr-project.org/
- https://github.com/rr-debugger/rr
- https://groups.google.com/g/rr-devel
- https://github.com/rr-debugger/rr/wiki/News
- https://chat.mozilla.org/#/room/#rr:mozilla.org
- Development sponsored by (Pernosco)[https://pernos.co/]
rr은 Linux용 기본 C/C++ 디버깅 도구가 되고자 하며, gdb를 대체하고 향상시킵니다. 실패를 한 번 기록한 다음, 원하는 횟수만큼 결정적으로 기록을 디버깅합니다. 매번 동일한 실행이 재생됩니다.
rr은 또한 gdb에서 효율적인 역방향 실행을 제공합니다. 중단점과 데이터 감시점을 설정하고 적중된 지점으로 빠르게 역방향 실행합니다.
rr은 실제 애플리케이션에서 작동하며 많은 개발자가 실제 버그를 수정하는 데 사용합니다. 어려운 버그를 디버깅하는 것을 훨씬 더 쉽게 만들지만 쉬운 버그의 디버깅도 빠르게 합니다.
-
특히 대부분 단일 스레드 작업 부하에서 다른 유사한 도구와 비교하여 오버헤드가 낮습니다.
-
Firefox, Chrome, QEMU, LibreOffice, Go 프로그램 등 모든 종류의 애플리케이션의 녹화 및 재생을 지원합니다.
-
전체 컨테이너를 포함한 다중 프로세스 작업 부하를 기록, 재생 및 디버깅합니다.
-
gdb 스크립팅 및 IDE 통합 과 함께 작동합니다.
-
기계 간 이식이 가능한 내구성이 뛰어나고 컴팩트한 트레이스
-
간헐적인 버그를 더 쉽게 재현할 수 있는 카오스 모드
rr을 사용하여 애플리케이션을 기록하는 것으로 시작하세요.
$ rr record /your/application --args
...
FAIL: oh no!
실패(FAIL)를 포함한 전체 실행이 디스크에 저장되었습니다. 이제 해당 기록을 디버깅할 수 있습니다.
$ rr replay
GNU gdb (GDB) ...
...
0x4cee2050 in _start () from /lib/ld-linux.so.2
(gdb)
기억하세요, 당신은 기록된 추적을 결정론적으로 디버깅하고 있습니다 . 라이브, 비결정론적 실행이 아닙니다 . 재생된 실행의 주소 공간, 레지스터 내용, syscall 데이터 등은 모든 실행에서 정확히 동일합니다.
일반적인 gdb 명령어를 대부분 사용할 수 있습니다.
(gdb) break mozilla::dom::HTMLMediaElement::HTMLMediaElement
...
(gdb) continue
Continuing.
...
Breakpoint 1, mozilla::dom::HTMLMediaElement::HTMLMediaElement (this=0x61362f70, aNodeInfo=...)
...
디버깅 세션을 다시 시작해야 하는 경우, 예를 들어 중요한 실행 지점에서 중단을 놓친 경우, 문제 없습니다. gdb run명령을 사용하여 리플레이를 다시 시작하세요.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
...
Breakpoint 1, mozilla::dom::HTMLMediaElement::HTMLMediaElement (this=0x61362f70, aNodeInfo=...)
...
(gdb)
이 run명령은 처음부터 귀하의 녹음에 대한 또 다른 재생 실행을 시작했습니다. 하지만 세션이 재시작된 후 동일한 실행이 다시 재생되었습니다. 그리고 모든 디버깅 상태는 재시작 후에도 보존되었습니다.
동적으로 할당된 객체의 포인터가 두 리플레이 세션에서 동일했음을 유의하세요 this. 메모리 할당은 각 리플레이에서 정확히 동일하므로 보고 싶은 주소를 하드코딩할 수 있습니다.
더욱 강력한 것은 역방향 실행입니다. Firefox 레이아웃을 디버깅한다고 가정해 보겠습니다.
Breakpoint 1, nsCanvasFrame::BuildDisplayList (this=0x2aaadd7dbeb0, aBuilder=0x7fffffffaaa0, aDirtyRect=..., aLists=...)
at /home/roc/mozilla-inbound/layout/generic/nsCanvasFrame.cpp:460
460 if (GetPrevInFlow()) {
(gdp) p mRect.width
12000
우리는 우연히 그 값이 틀렸다는 것을 알고 있습니다. 우리는 그것이 어디에 설정되었는지 알아내고 싶습니다. rr은 그것을 빠르고 쉽게 만들어줍니다.
Breakpoint 1, nsCanvasFrame::BuildDisplayList (this=0x2aaadd7dbeb0, aBuilder=0x7fffffffaaa0, aDirtyRect=..., aLists=...)
at /home/roc/mozilla-inbound/layout/generic/nsCanvasFrame.cpp:460
460 if (GetPrevInFlow()) {
(gdp) p mRect.width
12000
하드웨어 데이터 감시점과 역방향 실행을 결합하면 정말 강력해집니다!
다음 영상에서 rr로 Firefox를 녹화하고 재생하는 간단한 데모를 보여줍니다.
다음 영상에서는 rr의 기본 기능을 좀 더 자세히 보여줍니다.
다음 영상은 로버트 오칼라한이 rr에 관해 설명하는 고급 기술 강의입니다.
다음 지침을 따르세요. 패키지가 작동하지 않을 경우 권장 --- 커널 변경 및 OS 업데이트에는 때때로 rr 변경이 필요합니다.
cd /tmp
wget https://github.com/rr-debugger/rr/releases/download/5.8.0/rr-5.8.0-Linux-$(uname -m).rpm
sudo dnf install rr-5.8.0-Linux-$(uname -m).rpm
cd /tmp
wget https://github.com/rr-debugger/rr/releases/download/5.8.0/rr-5.8.0-Linux-$(uname -m).deb
sudo dpkg -i rr-5.8.0-Linux-$(uname -m).deb
rr의 사용 방법을 알아보려면 사용 지침을 따르세요 .
rr을 사용하여 Firefox를 디버깅하는 경우 이러한 설정 지침이 도움이 될 수 있습니다. rr을 사용하여 Firefox 테스트 모음을 기록하는 방법을 다룹니다.
rr의 원래 동기는 간헐적 오류의 디버깅을 더 쉽게 만드는 것이었습니다. 이러한 오류는 주어진 프로그램 실행이 오류를 보여주지 않을 수 있기 때문에 디버깅하기 어렵습니다. 우리는 오버헤드가 낮은 프로그램 실행을 기록하는 도구를 만들고 싶었습니다. 그러면 오류가 보일 때까지 테스트 실행을 기록한 다음, 완전히 이해될 때까지 디버거에서 실패한 실행을 반복해서 재생할 수 있습니다.
또한 결정적 재생이 모든 종류의 버그 디버깅을 더 쉽게 만들어 줄 것이라고 기대했습니다. 일반 디버거를 사용하면 디버깅 세션 중에 알게 된 정보(예: 관심 있는 객체의 주소, 중요한 이벤트의 순서)는 테스트 케이스를 다시 실행해야 할 때 종종 쓸모없게 됩니다. 결정적 재생을 사용하면 그런 일이 절대 일어나지 않습니다. 실패한 실행 중에 무슨 일이 일어나는지에 대한 지식이 단조롭게 증가합니다.
게다가 디버깅은 효과의 원인을 추적하는 과정이기 때문에 디버거가 시간을 거슬러 실행할 수 있다면 훨씬 더 쉽습니다. 재생 중에 재시작 가능한 체크포인트를 제공하는 기록/재생 시스템이 주어지면 이전 체크포인트를 복원하고 원하는 지점으로 정방향으로 실행하여 특정 시점으로 역방향 실행을 시뮬레이션할 수 있다는 것은 잘 알려진 사실입니다. 그래서 우리는 우리가 신경 쓰는 애플리케이션(Firefox)에서 잘 작동하는 오버헤드가 낮은 기록 및 재생 시스템을 빌드하면 gdb의 역방향 실행 명령에 대한 정말 유용한 백엔드를 빌드할 수 있을 것이라고 생각했습니다.
이러한 목표는 모두 달성되었습니다. rr은 작동하는 도구일 뿐만 아니라, 많은 대규모 및 소규모 프로젝트에서 개발자가 정기적으로 사용하고 있습니다.
rr은 Linux 사용자 공간 프로세스 그룹을 기록하고 커널에서 해당 프로세스로의 모든 입력과 해당 프로세스에서 수행된 비결정적 CPU 효과(매우 적음)를 캡처합니다. rr 재생은 실행이 명령어 수준 제어 흐름과 메모리 및 레지스터 내용을 보존하도록 보장합니다. 메모리 레이아웃은 항상 동일하고, 객체의 주소는 변경되지 않으며, 레지스터 값은 동일하고, syscall은 동일한 데이터를 반환합니다.
퍼저와 랜덤 폴트 인젝터와 같은 도구는 rr과 함께 사용하면 더욱 강력해집니다. 이러한 도구는 간헐적인 오류를 트리거하는 데 매우 뛰어나지 만 , 동일한 오류를 다시 재현하여 디버깅하는 것은 종종 어렵습니다 . rr을 사용하면 랜덤 실행을 간단히 기록할 수 있습니다. 실행이 실패하면 저장된 기록을 사용하여 문제를 결정적으로 디버깅할 수 있습니다.
rr은 버그 수정 비용을 낮춥니다. rr은 동일한 비용으로 더 높은 품질의 소프트웨어를 생산하는 데 도움이 됩니다. 또한 rr은 디버깅을 더 즐겁게 만듭니다
기록 및 재생 디버깅은 오래된 아이디어입니다. 많은 시스템이 rr보다 앞섰습니다. rr을 차별화하는 것은 설계 목표입니다.
-
Firefox에 대한 초기 초점 많은 기록 및 재생 기술에는 특정 프로그래밍 언어가 필요하거나 확장이 잘 되지 않아 Firefox를 처리할 수 없거나 실험적인 기술일 뿐이며 구체화되지 않았습니다. Firefox는 복잡한 애플리케이션이므로 rr이 Firefox 디버깅에 유용하기 때문에 일반적으로 유용할 가능성이 높습니다.
-
Deployability rr은 재고 Linux 커널, 상용 하드웨어에서 실행되며 시스템 구성 변경이 필요하지 않습니다. 많은 기록 및 재생 기술에는 커널 변경이 필요합니다. 많은 기술이 가상 시스템에서 OS를 실행하는 데 의존합니다.
-
낮은 런타임 오버로드 우리는 워크플로에서 rr이 gdb를 대체하기를 원합니다. 즉, gdb를 사용하는 경우만큼 빨리 rr로 결과를 얻기 시작해야 합니다. 오버헤드가 낮다는 것은 테스트의 섭동이 적다는 것을 의미합니다.
-
설계의 단순성 rr을 개발할 리소스가 많지 않았기 때문에 동적 바이너리 계측과 같은 복잡한 기술에 의존하는 접근 방식을 피했습니다. 이러한 단순성 덕분에 rr은 더욱 견고해지고 오버헤드가 낮아졌습니다.
rr의 오버헤드는 애플리케이션의 워크로드에 따라 달라집니다. Firefox 테스트 제품군에서는 rr의 녹화 성능이 상당히 유용합니다. 속도가 1.2배 이하로 느려집니다. 1.2배 느려지면 제품군을 자체적으로 실행하는 데 10분이 걸리는 경우 rr에서 녹화하는 데 약 12분이 걸립니다. 그러나 오버헤드는 워크로드에 따라 크게 달라질 수 있습니다. 대부분 단일 스레드 프로그램의 경우 rr은 우리가 알고 있는 경쟁 기록 및 재생 시스템보다 오버헤드가 훨씬 낮습니다.
-
단일 코어 머신을 에뮬레이트합니다. 따라서 병렬 프로그램은 단일 코어에서 실행 속도가 느려집니다. 이는 설계의 고유한 특징입니다.
-
기록 트리 외부의 프로세스와 메모리를 공유하는 프로세스를 기록할 수 없습니다. 이는 설계의 고유한 특징입니다. rr은 이 문제를 피하기 위해 기록된 프로세스에 대한 X 공유 메모리와 같은 기능을 자동으로 비활성화합니다.
-
상당히 현대적인 x86 CPU나 특정 ARM CPU(Apple M1+)가 필요합니다.
-
기록된 프로세스에서 실행되는 모든 시스템 호출에 대한 지식이 필요합니다. 이미 Firefox와 사람들이 rr로 처리한 다른 애플리케이션에서 필요한 광범위한 syscall을 지원하지만 지원이 완료되지 않았으므로 애플리케이션에서 rr을 실행하면 구현해야 하는 syscall이 발견될 수 있습니다. 지원되지 않는 시스템 호출에 대해서는 github 이슈를 제출 하세요.
-
커널 변경, 시스템 라이브러리 업데이트 또는 새로운 CPU 패밀리에 대응하여 업데이트해야 할 때가 있습니다. rr이 작동하지 않는 경우(위의 경고가 적용되지 않는 경우) 문제를 제출 하세요 .
확장된 기술 보고서는 rr 의 작동 방식과 성능을 가장 잘 간략하게 설명한 것입니다.
rr 위키 에는 rr과 관련된 기술적 주제를 다루는 페이지가 들어 있습니다.
rr에 대한 질문이 있으면 메일링 리스트 나 chat.mozilla.org의 #rr 에서 질문하세요 .
'Debug' 카테고리의 다른 글
gdb 메모리 접근 (0) | 2024.09.20 |
---|---|
[procdump] 윈도우즈 process(*.exe)의 crash 발생시 dump 생성 (0) | 2017.09.19 |
디버깅 훈련 : Debugging Applications (0) | 2008.11.06 |