Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

493
557
422263


[TRACE32] gcore 크래시 유틸리티로 유저 프로세스의 콜스택 보기! [Debugging] Tips

이번 포스팅에서는 크래시 유틸리티의 extensions인 gcore를 빌드하는 방법과 이 기능을 활용해 유저 프로세스의 스택을 추출하는 방법을 소개한다.

* gcore 소스 코드를 내려받기

'http://people.redhat.com/~anderson/extensions.html' url에 액세스한 다음에, 
crash-gcore-command-1.5.1.tar.gz 파일을 내려받는다.

url: http://people.redhat.com/~anderson/extensions.html
crash-gcore-command-1.5.1.tar.gz

crash-gcore-command-1.5.1.tar.gz 파일을 받은 다음에 압축을 푼다.

* gcore 소스 코드를 빌드하기

먼저 크래시 유틸리티의 소스 코드를 빌드한다. (ARM64 아키텍처를 기준)
$ make target=ARM64

크래시 유틸리티의 소스에서 extensions 디렉토리로 이동한다.

austindh.kim:~/bin/crash_src/crash/extensions$ ls
COPYING  defs.h  dminfo.c  echo.c  eppic  eppic.c  eppic.mk  libgcore  Makefile  snap.c  snap.mk  trace.c

gcore 유틸리티의 소스 코드를 extensions 폴더로 복사한다.

austindh.kim:~/bin/crash_src/crash/extensions$ cp -r ~austindh.kim/bin/gcore-command-1.5.1/crash-gcore-command-1.5.1/* .
austindh.kim:~/bin/crash_src/crash/extensions$ ls
COPYING  defs.h  dminfo.c  echo.c  eppic  eppic.c  eppic.mk  gcore.c  gcore.mk  libgcore  Makefile  snap.c  snap.mk  trace.c

gcore의 소스 코드를 복사한 후 gcore.c와 gcore.mk 파일이 보일 것이다. 그럼 제대로 복사가 된 것이다.

크래시 유틸리티의 최상단 디렉토리로 이동한 후 'make target=ARM64 extensions' 명령어를 입력해 extensions 기능을 빌드한다. 

austindh.kim:~/bin/crash_src/crash$ make target=ARM64 extensions
gcc -Wall -g -shared -rdynamic -o echo.so echo.c -fPIC -DARM64  -DGDB_7_6
cd eppic/libeppic && make

extensions 디렉터리로 이동하면 gcore.so이란 라이브러리 파일이 제대로 생성됐음을 확인할 수 있다.

austindh.kim:~/bin/crash_src/crash/extensions$ ls
COPYING  dminfo.c   echo.c   eppic    eppic.mk  gcore.c   gcore.so  Makefile  snap.mk  trace.so
defs.h   dminfo.so  echo.so  eppic.c  eppic.so  gcore.mk  libgcore  snap.c    trace.c

크래시 유틸리티를 실행한 다음에 gcore.so 라이브러리 파일을 extension 명령어로 로딩한다.

crash64> extend /home007/austindh.kim/bin/Crash64Tool/extensions/gcore.so
/home007/austindh.kim/bin/Crash64Tool/extensions/gcore.so: shared object loaded

'shared object loaded' 메시지가 보이니 제대로 gcore.so 라이브러리 파일이 로딩됐음을 알 수 있다.

* 크래시 유틸리티에서 gcore.so 파일을 로딩하기

이제 PID가 1인 init 프로세스의 유저 공간을 덤프해보자.
이를 위해 'gcore [pid]' 명령어를 입력해야 한다.

crash64> gcore 1
gcore: WARNING: page fault at 64a000
gcore: WARNING: page fault at 64b000
gcore: WARNING: page fault at 64e000
gcore: WARNING: page fault at 651000
gcore: WARNING: page fault at 652000
gcore: WARNING: page fault at 659000
gcore: WARNING: page fault at 7f78601000
gcore: WARNING: page fault at 7f78602000
...
gcore: WARNING: page fault at 7fc2740000
gcore: WARNING: page fault at 7fc2741000
Saved core.1.init

'WARNING: page fault' 메시지는 False Positive 이니 너무 겁먹지 말자.

* TRACE32로 gcore 덤프 파일을 로딩하기

이제 gcore로 추출한 덤프 파일을 TRACE32 프로그램으로 로딩하자.

Data.LOAD.binary core.1.init 0x7FC20FD000
Data.LOAD.elf init 

참고로 0x7FC20FD000
 오프셋은 gcore 메타 해더 오프셋을 고려해 계산했다.
0x7FC20FD000 = 0x7FC2742000 - 0x645000

커널 스택 주소의 스택 최하단에 위치한 '유저 프로세스의 레지스터 세트'정보를 참고해 레지스터 세트를 설정한다.
TRACE32 명령어는 다음과 같다.
 
$ r.s X29   0x7FC2744110
$ r.s X30                  0
$ r.s PC            0x419344
$ r.s SP    0x7FC27440D0
$ v.f

이제 유저 공간에서 실행 중인 init 프로세스의 콜스택을 볼 수 있다.

-000|std::__1::__compressed_pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allo
-000|std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(
-000|android::init::SocketConnection::source_context(?)
-001|std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(
-001|android::init::handle_property_set_fd()
-002|android::init::main(?, ?)
-003|main(?, ?)
-004|__libc_init(?, ?, slingshot = 0x00403698, structors = 0x0000007FC2744600)
 ---|end of frame


덧글

  • Paran Lee 2022/09/25 09:44 # 삭제 답글

    감사합니다~ 동현님!
    큰 도움이 되었네요. 다른 extension 플러그인도 좀 더 연구해봐야겠어요!
    - https://crash-utility.github.io/extensions.html
    좋은 하루되세요!
  • Paran Lee 2022/09/25 09:48 # 삭제 답글

    포스팅에 안드로이드 PID 1 인 init 프로세스는 C++ 로 짜여져 있나보네요. ㅎㅎ
    android 가 실체는 자바로 짜는 앱 프레임워크가 아니라, android 라는 init 프로세스를 말하는 거였군요.
  • Paran Lee 2022/09/25 14:35 # 삭제 답글

    vmcore 에 담긴 덤프된 메모리 영역은 커널 뿐만 아니라, 유저 부분까지 모두 있나보네요?
    KDump는 커널에 매핑한(유저 프로세스의 스택, 힙, 데이터 영역 포함) 모든 메모리 영역을 덤프하는 건가요?
  • AustinKim 2022/09/27 11:48 #

    커널 패닉이 발생한 프로세스와 해당 프로세스가 속한 프로세스 그룹에 있는 프로세스들에 대해 유저 공간까지 메모리가 덤프됩니다. 그런데 커널 크래시가 발생한 시점의 모든 프로세스의 유저 공간 메모리는 덤프되지는 않습니다.
  • Paran Lee 2022/09/27 13:20 # 삭제 답글

    답변 감사합니다~
  • AustinKim 2022/09/27 13:34 #

    유저 공간 덤프를 추출하는 방법과 gcore 사용 방법은 조만간 블로그에 올릴 예정이에요.
  • Paran Lee 2022/09/27 19:33 # 삭제

    네 감사합니다!
    유저 공간 덤프는 유저 프로세스 덤프인가요?
    아니면 vmcore 에서 추출한 유저 덤프 말하시는 건가요?
  • AustinKim 2022/09/27 21:31 #

    vmcore 에서 추출한 유저 덤프입니다.
댓글 입력 영역