Linux addr2line 구체 적 인 응용 지침

zSeries 의 Linux 응용 프로그램 을 디 버 깅 하 는 것 은 다른 시스템 구조의 Linux 응용 프로그램 을 디 버 깅 하 는 것 과 유사 하 다.경험 이 있 는 리 눅 스 개발 자 에 게 가장 큰 도전 은 새로운 시스템 구 조 를 이해 하 는 것 이다.리 눅 스 를 처음 접 한 대형 컴퓨터 개발 자 들 에 게 새로운 디 버 깅 도 구 를 파악 하 는 것 은 두 려 운 임무 인 것 같다.겁 먹 지 마.본 고 는 리 눅 스 addr2line 의 입문 을 돕 기 위해 유용 한 힌트 를 제공 할 것 입 니 다.UserDebug 로그 기록
무 너 진 프로그램 을 디 버 깅 하 는 첫 번 째 단 계 는 어디 가 잘못 되 었 는 지 알 아 내 는 것 이다.zSeries 의 Linux 커 널 은 사용자 프로 세 스 가 붕 괴 될 때 기본 적 인 디 버 깅 정 보 를 기록 하 는 내장 기능 을 가지 고 있 습 니 다.이 기능 을 사용 하려 면 루트 사용자 로 다음 명령 을 실행 하 십시오: echo 1 > / proc / sys / kernel / userprocessdebug
프로 세 스 가 충돌 할 때 로그 파일 (/ var / log / messages) 에는 프로그램 종료 원인, 고장 주소, 프로그램 상태 글자 (PSW), 유 니 버 설 레지스터, 액세스 레지스터 를 포함 한 간단 한 레지스터 덤 프 가 포 함 됩 니 다. 

  
  
  
  
  1. Mar3111:34:28l02kernel:Userprocessfault:interruptioncode0x10  
  2. Mar3111:34:28l02kernel:failingaddress:0  
  3. Mar3111:34:28l02kernel:CPU:1  
  4. Mar3111:34:28l02kernel:Processsimple(pid:30122,stackpage=05889000)  
  5. Mar3111:34:28l02kernel:  
  6. Mar3111:34:28l02kernel:UserPSW:070dc000c00ab738  
  7. Mar3111:34:28l02kernel:task:05888000ksp:05889f08pt_regs:05889f68  
  8. Mar3111:34:28l02kernel:UserGPRS:Mar3111:34:28l02kernel:00000000004019a0004019a000000000  
  9. Mar3111:34:28l02kernel:00000003c00ab732004008f800400338  
  10. Mar3111:34:28l02kernel:40018ffc0040061c40018e347ffff800  
  11. Mar3111:34:28l02kernel:00400434804006248040066e7ffff800  
  12. Mar3111:34:28l02kernel:UserACRS:  
  13. Mar3111:34:28l02kernel:00000000000000000000000000000000  
  14. Mar3111:34:28l02kernel:00000001000000000000000000000000  
  15. Mar3111:34:28l02kernel:00000000000000000000000000000000  
  16. Mar3111:34:28l02kernel:00000000000000000000000000000000  
  17. Mar3111:34:28l02kernel:UserCode:  
  18. Mar3111:34:28l02kernel:4440500007fea74a0001185418431835a8240000  

위 에 표 시 된 프로그램 ("simple") 은 프로그램 인 터 럽 트 코드 0x 10 으로 종료 되 며, 고장 주 소 는 0 입 니 다.누 군가 빈 지침 을 사용 한 것 은 분명 하 다.지금 우 리 는 무슨 일이 일 어 났 는 지 알 고 있다. 다음은 그것 이 어디에서 일 어 났 는 지 확실히 알 아야 한다.
Linux addr2line 기본 진단
UserDebug 로그 항목 이 제공 하 는 정 보 는 프로그램의 충돌 위 치 를 확인 하 는 데 사용 할 수 있 습 니 다.사용 가능 한 도구 들 은 프로그램 종료 문 제 를 해결 하 는 데 도움 을 줄 수 있 습 니 다.우 리 는 본문 에서 점차 그 공구 들 을 소개 할 것 이다.
우선 이 로그 항목 의 사용자 PSW 를 확인 합 니 다.이 PSW 는 명령 주소, 상태 코드 및 기계 상태 에 대한 기타 정 보 를 포함 하고 있다.현재 우 리 는 지령 주소 (33 위 에서 63 위) 에 만 관심 을 갖 고 있다.간소화 하기 위해 서, 사용자 PSW 가 070 dc 00080400618 이 라 고 가정 합 시다.기억 하 세 요. 우 리 는 ESA / 390 (31 비트 주소 지정) PSW 를 고찰 하고 있 습 니 다.32 위 는 명령 주소 의 일부분 이 아니 라 31 비트 주소 지정 모드 를 표시 하 는 표지 이지 만 PSW 값 을 연구 할 때 처리 해 야 합 니 다.실제 지령 지침 을 얻 기 위해 서 는 PSW 의 두 번 째 글 자 를 0x 80000000 으로 줄 일 수 있다.결 과 는 명령 주소 0x 400618 입 니 다.코드 를 찾 으 려 면 파일 에 있 는 정 보 를 실행 할 수 있어 야 합 니 다.우선 readelf 를 사용 하여 프로그램 헤더 정 보 를 인쇄 합 니 다. 

  
  
  
  
  1. ElffiletypeisEXEC(Executablefile)Entrypoint0x400474Thereare6programheaders,startingatoffset52ProgramHeaders:  
  2. TypeOffsetVirtAddrPhysAddrFileSizMemSizFlgAlign  
  3. PHDR0x0000340x004000340x004000340x000c00x000c0RE0x4  
  4. INTERP0x0000f40x004000f40x004000f40x0000d0x0000dR0x1[Requestingprograminterpreter:/lib/ld.so.1]  
  5. LOAD0x0000000x004000000x004000000x009900x00990RE0x1000  
  6. LOAD0x0009900x004019900x004019900x000fc0x00114RW0x1000  
  7. DYNAMIC0x0009ac0x004019ac0x004019ac0x000a00x000a0RW0x4  
  8. NOTE0x0001040x004001040x004001040x000200x00020R0x4  
  9. SectiontoSegmentmapping:SegmentSections...  
  10. 00  
  11. 01.interp  
  12. 02.interp.note.ABI-tag.hash.dynsym.dynstr.gnu.version  
  13. .gnu.version_r.rela.got.rela.plt.init.plt.text.fini.rodata  
  14. 03.data.eh_frame.dynamic.ctors.dtors.got.bss  
  15. 04.dynamic  
  16. 05.note.ABI-tag  

위 는 readelf - lssimple 의 결 과 를 보 여 줍 니 다.ProgramHeaders 부분 에서 첫 번 째 LOAD 줄 은 프로그램 이 어디에서 불 러 오 는 지 에 대한 정 보 를 제공 합 니 다.Flg 열 에서 이 단락 은 R (read) E (executable) 로 표 시 됩 니 다.VirtAddr 는 프로그램 이 불 러 오기 시작 한 주소 입 니 다.MemSiz 는 이 단락 에 불 러 오 는 코드 길이 입 니 다.그것 을 VirtAddr 에 추가 하면 이 프로그램의 기본 주소 범 위 는 0x 400000 - 0x 400990 이다.프로그램 이 충돌 하 는 명령 주 소 는 0x 400618 로 프로그램의 로드 범위 안에 있 습 니 다.이제 우 리 는 문제 가 코드 에서 직접 발생 한 다 는 것 을 알 게 되 었 다.
실행 가능 한 파일 에 디 버 깅 기 호 를 포함 하면 어떤 줄 코드 가 문 제 를 일 으 켰 는 지 확인 할 수 있 습 니 다.이 주소 와 실행 가능 한 파일 에 addr2line 프로그램 을 사용 합 니 다. 다음 과 같 습 니 다: addr2line - simple0x 400618
반환: / home / devuser / simple. c: 34
이 문 제 를 연구 하려 면 34 번 째 줄 을 검사 할 수 있다.
Linux addr2line 의 원본 프로그램 이 무 너 지면 PSW 는 070 dc000c00ab 738 입 니 다.명령 주 소 를 얻 으 려 면 0x 80000000 을 줄 일 수 있 습 니 다.결 과 는 0x400ab 738 이다.이 주 소 는 결코 정확하게 우리 의 작은 프로그램 안에 떨 어 지지 않 았 다.그럼, 그것 은 무엇 입 니까?공유 라 이브 러 리 에서 온 코드 입 니 다.실행 가능 한 파일 에 Id 명령 (lddsimple) 을 실행 하면 프로그램 실행 에 필요 한 공유 대상 의 목록 과 이 라 이브 러 리 가 사용 할 수 있 는 주 소 를 되 돌려 줍 니 다.libc.so.6=>/lib/libc.so.6(0x40021000)/lib/ld.so.1=>/lib/ld.so.1(0x40000000)
이 명령 주 소 는 libc. so. 6 을 불 러 오 는 주소 에 대응 합 니 다.우리 의 간단 한 테스트 사례 중 두 개의 공유 대상 만 필요 하 다.다른 프로그램 은 더 많은 공유 대상 이 필요 할 수 있 습 니 다. 이것 은 ldd 의 출력 을 더욱 복잡 하 게 할 수 있 습 니 다.우 리 는 perl 을 예 로 들 것 이다.입력: ldd / usr / bin / perl
획득: 

  
  
  
  
  1. libnsl.so.1=> 
  2. /lib/libnsl.so.1(0x40021000)libdl.so.2=> 
  3. /lib/libdl.so.2(0x40039000)libm.so.6=> 
  4. /lib/libm.so.6(0x4003d000)libc.so.6=> 
  5. /lib/libc.so.6(0x40064000)libcrypt.so.1=> 
  6. /lib/libcrypt.so.1(0x4018f000)/lib/ld.so.1=> 
  7. /lib/ld.so.1(0x40000000)  

필요 한 모든 것 이 거기에 있 지만, 나 는 이 프로 세 스에 대해 아래 의 내용 을 좀 더 빨리 읽 는 것 을 발견 했다. 

  
  
  
  
  1. ldd/usr/bin/perl|awk‘{print?$4““$3}’  
  2. |sort(0x40000000)/lib/ld.so.1(0x40021000)  
  3. /lib/libnsl.so.1(0x40039000)  
  4. /lib/libdl.so.2(0x4003d000)  
  5. /lib/libm.so.6(0x40064000)  
  6. /lib/libc.so.6(0x4018f000)  
  7. /lib/libcrypt.so.1  

이제 리 눅 스 addr2line 붕괴 가 libc 에서 발생 한 곳 을 확인 합 니 다.libc. so. 6 의 로드 주 소 는 0x 40021000 이 라 고 가정 하고 명령 주소 0x400ab 738 에서 이 를 빼 면 결 과 는 0x8a 738 이다.이것 은 libc. so. 6 에 들 어 가 는 오프셋 입 니 다.nm 명령 을 사용 하여 libc. so. 6 덤 프 기호 에서 이 주소 가 어느 함수 에 있 는 지 확인 하려 고 합 니 다.libc. so. 6 에 대해 nm 는 7, 000 여 줄 의 출력 을 생 성 합 니 다.계 산 된 오프셋 부분 에 grep (정규 표현 식 검색 프로그램) 을 실행 하면 검사 해 야 할 데이터 양 을 줄 일 수 있 습 니 다.입력: nm / lib / libc. so. 6 | sort | grep0008a
66 줄 로 되 돌아 갑 니 다. 이 출력 중간 에 우 리 는 0008 a6fcTmemcpy 0008 a754 t 를 발견 할 수 있 습 니 다.wordcopy_fwd_aligned
이 오프셋 은 memcpy 의 한 위치 에 있 습 니 다.이 예 에서 빈 포인터 가 목표 주소 로 memcpy 에 전달 되 었 습 니 다.우리 가 어디에서 호출 한 memcpy 입 니까?잘 했 어.로그 파일 에 출력 된 레지스터 덤 프 를 검사 해서 대상 영역 을 확인 할 수 있 습 니 다.레지스터 14 는 함수 호출 을 실행 할 때의 반환 주 소 를 포함 합 니 다.그림 1 에 따 르 면 R14 는 0x 8040066e 로 높 은 위 치 를 캡 처 한 후에 주소 0x 40066e 가 생 긴 다.이 주 소 는 프로그램 범위 안에 있 기 때문에 addr2line 을 실행 하여 이 주소 가 어디 에 있 는 지 확인 할 수 있 습 니 다.입력: addr2line - simple0x40066e
반환: / home / devuser / simple. c: 36
이것 은 우리 가 memcpy 를 호출 한 후의 그 줄 이다.addr2line 에 대한 보충: 실행 가능 한 파일 에 디 버 깅 기호 가 포함 되 어 있 지 않 으 면 얻 을 수 있 습 니까?:0 을 응답 으로 한다.
 
 
 
 
arm-eabi-addr2line 
Usage: arm-eabi-addr2line [option(s)] [addr(s)]
for example:
D:\gat\iBox\TRUNK\lib>arm-eabi-addr2line -e "D:\*.out.symbols\alps\out\target\product\*\symbols/../../../../../kernel/vmlinux" c0037aa0
 The options are:   @                Read options from   -b --target=  Set the binary file format   -e --exe=  Set the input file name (default is a.out)   -i --inlines           Unwind inlined functions   -j --section=    Read section-relative offsets instead of addresses   -s --basenames         Strip directory names   -f --functions         Show function names   -C --demangle[=style]  Demangle function names   -h --help              Display this information   -v --version           Display the program's version.
상용 - f, - C, - e.
 
KE debug 방법:
먼저 Dump 의 kernel log 에서 [< >] 와 같은 것 을 찾 은 다음 addr2line 을 통 해 vmlinux 에서 해당 하 는 line 을 찾 습 니 다.
어떤 주소, 예 를 들 어 bf 는 debug 로 시작 할 수 없습니다. 3GB - 8MB ~ 3GB 는 kernel module 에서 불 러 온 주소 이 고 vmlinux 에는 module 의 symbol table 이 없습니다.
NE debug 방법
먼저 원 로그 에서 signal 11 (SIGSEGV), fault addr baae8fd 1 을 찾 습 니 다.
물건
분석 을 통 해 fault addr 가 deaddead 라면 heap error 가 나타 난 다음 에 deadadd 0 으로 보면 heap corruption 이 고 deadadd 0 이 라면 heap usage error 입 니 다.
그리고 힙 정 보 를 저장 하고 다운로드 합 니 다.
그리고 signal 11 (SIGSEGV), fault addr baae8fd 1 의 주 소 를 addr2line 을 통 해 채널 C 라 이브 러 리 에서 오류 가 발생 한 주 소 를 변환 합 니 다.
NE 의 decode 는 통과 입 니 다.
         #01  pc 0001cd4a  /system/lib/libc.so
중간 뒤의 libc. so 경 로 를 symbols path 뒤에 추가 한 다음 addr2line 을 통 해 해석 합 니 다.
 arm-eabi-addr2line -f -C -e D:\gat\Department\SP_SS\OSS5_ST_Share\GAT\TRUNK\Test_Cases\NE\ztemt73v2_ALPS.GB.p52_eng.out.symbols\alps\out\target\product\ztemt73v2\symbols\system\lib\libc.so 0001cd0e
출력 하면...
__findenv /alps/GB/Of/alps/bionic/libc/stdlib/getenv.c:90

좋은 웹페이지 즐겨찾기