itsource

segfault 커널 로그 메시지를 읽는 방법

mycopycode 2022. 10. 15. 09:12
반응형

segfault 커널 로그 메시지를 읽는 방법

수 디버깅을 시도하면 다음 합니다.어플리케이션을 디버깅하려고 합니다.세그먼트 폴트kern.log

kernel: myapp[15514]: segfault at 794ef0 ip 080513b sp 794ef0 error 6 in myapp[8048000+24000]

다음은 질문입니다.

  1. segfault의 diff 에러 번호에 관한 문서가 있습니까?이 예에서는 에러 6이지만, 에러 4, 5를 본 적이 있습니다.

  2. 입니까?at bf794ef0 ip 0805130b sp bf794ef0 and myapp[8048000+24000]

할 수 , 할 는 기호로 컴파일 할 수 있었어요. 그리고 제가 할 때x 0x8048000+24000기호가 반환되는데, 이게 올바른 방법인가요?지금까지의 제 추측은 다음과 같습니다.

  • sp = 스택 포인터?
  • ip = 명령 포인터
  • =에서?--
  • myapp[8048000+24000] = 기호 주소?

리포트가 공유 라이브러리가 아닌 프로그램을 가리킬 때

실행합니다.addr2line -e myapp 080513b(및 지정된 다른 명령 포인터 값에 대해서도 반복) 에러가 발생하고 있는 장소를 확인합니다.build를 debug-instrumented build .

공유 라이브러리인 경우

서서 libfoo.so[NNNNNN+YYYY] 부,, ★★NNNNNN라이브러리가 로드된 장소입니다. 포인터에서 뺍니다( ).ip)에 오프셋이 포함되어 있습니다..so위반하는 명령입니다.ㄴ, ㄴ, ㄴ, ㄴ, ㄴ데.objdump -DCgl libfoo.so해당 오프셋의 명령을 검색합니다.ASM 라벨에서 어떤 기능인지 쉽게 알 수 있을 것입니다. 경우,.so 수 .addr2line -e libfoo.so <offset>.

에러의 의미

다음은 필드에 대한 내역입니다.

  • address- 코드가 액세스하려고 하는 메모리 내의 위치(아마도10 ★★★★★★★★★★★★★★★★★」11만, 그 는 「」를 가리키고 있습니다.0)
  • ip 포인터, 이 하는 위치 - 명 、 - 、 - 、 - 、 - 、 , 、 ,,,,,,,, 。
  • sp - "스택 포인터"
  • error 고유의 를 참조해 주세요.를 참조해 주세요.arch/*/mm/fault.c용하사

나의 제한된 지식에 따르면 당신의 추측은 옳습니다.

  • sp= 포인터 = 스택 포인터
  • ip= 포인터 = 명령 포인터
  • myapp[8048000+24000]= = 주소

이 문제를 디버깅하고 있는 경우는, 코어 덤프를 생성하도록 코드를 수정하거나, 크래시시에 스택의 역추적을 기록합니다.GDB에서 프로그램을 실행할 수도 있습니다(또는 첨부할 수도 있습니다.

이 에러 코드는, 페이지 폴트의 아키텍처 에러 코드일 뿐이며, 아키텍처에 고유한 것 같습니다.은 종종 에 되어 있다.arch/*/mm/fault.c커널 소스에 있습니다.내 카피Linux/arch/i386/mm/fault.cerror_code에 대한 정의는 다음과 같습니다.

  • 비트 0 == 0은 페이지를 찾을 수 없음을 의미하며, 1은 보호 장애를 의미합니다.
  • 비트 1 == 0은 읽음, 1은 쓰기를 의미합니다.
  • 비트 2 == 0은 커널, 1은 사용자 모드를 의미합니다.

내 카피Linux/arch/x86_64/mm/fault.c에 다음 항목이 추가됩니다.

  • 비트 3 == 1은 고장이 명령 가져오기임을 의미합니다.

공유 라이브러리인 경우

유감스럽게도, 실제로는, 동적 링커에 의해서 라이브러리가 메모리내의 어디에 배치되어 있는지를 알 수 없습니다.

음, 이진수에서가 아니라 객체에서 정보를 얻을 수 있는 가능성은 여전히 있습니다.그러나 개체의 기본 주소가 필요합니다.또한 이 정보는 여전히 코어 덤프의 link_map 구조 내에 있습니다.

먼저 structure link_map을 GDB로 Import합니다.따라서 debug 기호가 있는 프로그램을 컴파일하여 GDB에 추가합니다.

링크.c

#include <link.h>
toto(){struct link_map * s = 0x400;}

get_baseaddr_from_coredump.

#!/bin/bash

BINARY=$(which myapplication)

IsBinPIE ()
{
    readelf -h $1|grep 'Type' |grep "EXEC">/dev/null || return 0
    return 1
}

Hex2Decimal ()
{
    export number="`echo "$1" | sed -e 's:^0[xX]::' | tr '[a-f]' '[A-F]'`"
    export number=`echo "ibase=16; $number" | bc`
}

GetBinaryLength ()
{
    if [ $# != 1 ]; then
    echo "Error, no argument provided"
    fi
    IsBinPIE $1 || (echo "ET_EXEC file, need a base_address"; exit 0)
    export totalsize=0
    # Get PT_LOAD's size segment out of Program Header Table (ELF format)
    export sizes="$(readelf -l $1 |grep LOAD |awk '{print $6}'|tr '\n' ' ')"
    for size in $sizes
    do Hex2Decimal "$size"; export totalsize=$(expr $number + $totalsize); export totalsize=$(expr $number + $totalsize)
    done
    return $totalsize
}

if [ $# = 1 ]; then
    echo "Using binary $1"
    IsBinPIE $1 && (echo "NOT ET_EXEC, need a base_address..."; exit 0)
    BINARY=$1
fi

gcc -g3 -fPIC -shared link.c -o link.so

GOTADDR=$(readelf -S $BINARY|grep -E '\.got.plt[ \t]'|awk '{print $4}')

echo "First do the following command :"
echo file $BINARY
echo add-symbol-file ./link.so 0x0
read
echo "Now copy/paste the following into your gdb session with attached coredump"
cat <<EOF
set \$linkmapaddr = *(0x$GOTADDR + 4)
set \$mylinkmap = (struct link_map *) \$linkmapaddr
while (\$mylinkmap != 0)
if (\$mylinkmap->l_addr)
printf "add-symbol-file .%s %#.08x\n", \$mylinkmap->l_name, \$mylinkmap->l_addr
end
set \$mylinkmap = \$mylinkmap->l_next
end

GDB 명령어 세트 내에서 link_map 콘텐츠 전체를 출력합니다.

그 자체는 그다지 중요하지 않은 것처럼 보이지만, 여기서 설명하는 공유 객체의 base_addr을 사용하면 관련된 공유 객체를 다른 GDB 인스턴스에서 직접 디버깅하여 주소에서 더 많은 정보를 얻을 수 있습니다.기호의 idee를 가지려면 첫 번째 gdb를 유지합니다.

메모: 스크립트가 다소 불완전합니다.이 값을 사용하여 합계를 인쇄한 add-symbol-file의 두 번째 파라미터에 추가할 수 있습니다.

readelf -S $SO_PATH|grep -E '\.text[ \t]'|awk '{print $5}'

여기서 $SO_PATH는 add-symbol-file의 첫 번째 인수입니다.

도움이 되었으면 좋겠다

언급URL : https://stackoverflow.com/questions/2179403/how-do-you-read-a-segfault-kernel-log-message

반응형