IT Share you

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

shareyou 2020. 12. 1. 20:04
반응형

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


이것은 매우 간단한 질문이 될 수 있습니다. 다음과 같은 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 = 명령 포인터
  • at = ????
  • myapp [8048000 + 24000] = 심볼 주소?

보고서가 공유 라이브러리가 아닌 프로그램을 가리키는 경우

addr2line -e myapp 080513b오류가 발생한 위치를 확인하려면 실행 (및 주어진 다른 명령 포인터 값에 대해 반복)합니다. 더 나은 방법은 디버그 계측 된 빌드를 얻고 gdb와 같은 디버거에서 문제를 재현하는 것입니다.

공유 라이브러리 인 경우

에서 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.c에는 error_code에 대한 다음 정의가 있습니다.

  • 비트 0 == 0은 페이지가 없음을 의미하고 1은 보호 오류를 의미합니다.
  • 비트 1 == 0은 읽기, 1은 쓰기를 의미합니다.
  • 비트 2 == 0은 커널, 1은 사용자 모드를 의미합니다.

내 사본은 Linux/arch/x86_64/mm/fault.c다음 추가합니다.

  • 비트 3 == 1은 오류가 명령 페치임을 의미합니다.

공유 라이브러리 인 경우

불행히도 당신은 물에 빠져 있습니다. 사후 동적 링커에 의해 라이브러리가 메모리에 배치 된 위치를 알 수 없습니다 .

음, 바이너리가 아니라 객체에서 정보를 검색 할 가능성이 여전히 있습니다. 그러나 객체의 기본 주소가 필요합니다. 그리고이 정보는 여전히 link_map 구조의 coredump 내에 있습니다.

따라서 먼저 link_map 구조체를 GDB로 가져오고 싶습니다. 따라서 디버그 기호로 프로그램을 컴파일하고 GDB에 추가해 보겠습니다.

link.c

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

get_baseaddr_from_coredump.sh

#!/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를 유지하십시오.

NOTE : the script is rather incomplete i suspect you may add to the second parameter of add-symbol-file printed the sum with this value :

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

where $SO_PATH is the first argument of the add-symbol-file

Hope it helps

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

반응형