Segmentation fault발생 시 address를 가지고 처리하는 방법

twins99의 이미지

SIGSEGV가 발생한 경우 siginfo_t.si_addr에 발생한 memory address가 저장되는 것으로 알고 있습니다.

그런데, 이 signal이 발생된 memory 번지를 가지고 어떻게 실제 코드를 찾아갈 수 있을까요?

일단 process number도 siginfo_t에 저장되어 있지만, 단순히 어느 process에 어느 번지다 라고만 가지고는

어렵지 않을까요?

어떤 방법이 있는지 궁금합니다.

twins99의 이미지

아시는분 답변 부탁드립니다.

익명사용자의 이미지

signal handler에서 ucontext_t parameter를 받지 않나요?

twins99의 이미지

내용을 정확하게 이해하지 못했습니다. 죄송합니다만, 좀더 상세하게 설명 부탁드립니다..

철이^^v의 이미지

address 를 가지고 실제 코드를 찾아가는 방법은 objdump 를 쓰시면 됩니다.
문제가 발생한 elf 파일과 소스가 있다면,
> objdump -S --start-address=0x######## --stop-address=0x########
이런 식으로 address range를 주어서 해당 address 범위의 소스를 찾아낼수 있답니다.

익명사용자의 이미지

질문하신 분은... 아마도 커널레벨에서 추적하고 싶으신 모양입니다.

twins99의 이미지

임베디드 환경에서 코딩중인데, 실행 시 죽었을 때 죽은 위치(address)는 얻었습니다만, 실제 제가 짠 코드 어디서 segmentation fault를 유발 시켰는지 알수가 없었습니다.
그래서 해당 address를 가지고 실제 제가 짠 코드의 위치를 알고자 했던 것인데요..

위 objdump를 사용해 이 위치를 알 수 있는 것인지요..혹 불가능 하다면 어떤 다른 방법이 있을까요..?

Hyun의 이미지

흠...
cross gcc 로 컴팔할때 -g -O0옵션을 주고 컴팔해서
타겟에서 실행하기 전에 ulimit -c unlimited 실행해서 core dump를 만들게 해주구요...
프로그램 실행해서 core dump가 생기면... gdb로 gdb my.exec.program core 실행해서 보면... 친절히 소스레벨 몇번째줄에서 죽었는지 나올껍니다...

예전에 듣기론 cross gdb로는 target의 core 파일을 분석할 수 없다고 들었는데...(어디 보니 최신버전 gdb에선 해결했다는 소문도...) cross gdb로 작업하시지 마시고 native gdb를 만들어서 사용하세요...

native gdb를 만들려면... 삽질이 좀 필요한데 먼저 cross gcc로 native gcc를 만든 후에 native gcc로 native gdb를 만들었던거 같은데...

혹시 개발환경을 어디서 제공받아쓰신다면 제공해주는 쪽에서 native gdb, native gcc등은 제공해줄껍니다...

twins99의 이미지

일단 위 방법 중 objdump를 사용한 방법으로 어느 위치에서 fault가 발생 하였는지는 확인 하였습니다.

그런데,

main()
{
char *p;
sprintf(p,"%s","HAHAHA");
}

와 같이 coding한 후 돌렸을 때
/lib/ld-linux.so.2속의 위치를 알려주네요..

즉 sprintf의 내부 어딘가에서 죽을 때 그 위치를 알려준다는 것이죠.

하지만, 제가 알고 싶은것은 'main 함수 내의 error발생 위치 입니다'
이 위치를 알기 위한 방법이 있을까요?

짧은 제 생각엔, call stack을 뒤져야 가능 할 것 같은데, 전혀 방법을 모르겠습니다.

혹은 죽을 때 memory dump가 일어나고 죽는다고 하였는데, 이 dump를 분석하면 가능하지 않을까요?

이 dump를 사용해 분석하는 방법이 있다면 알려주셨으면 합니다. dump의 저장위치나, 보는법 같은, 어떤 내용이라도 괜찮습니다.

답변 부탁드립니다.

김성진의 이미지

음..쉬운 질문은 아니지만, 공부가 필요한 부분입니다.

뉴스그룹에도 보면 간간히 sybase 엔진 개발자들도 이런 질문들을 하곤 합니다. -_-;;

StackFrame에 대해 공부를 하시구요, 그러면 이전 StackFrame으로 찾아가는 방법에 대해서

이해하실 수 있습니다.

무엇을 원하시는지 저는 정확히 알고 있으니, 이렇게 공부를 먼저 하시는 게 좋을 것 같네요.

참고로, mpatrol 과 같은 소스에서 stack backtrace에 대한 것을 찾으실 수 있습니다.

대략적으로

Segmentation Fault가 발생하면, 해당 시그널 핸들러가 불려집니다.

이 핸들러는 직접 설정하셔야지요.

그러면, 그 핸들러에서 ucontext 정보를 얻어서 그 중의 멤버 하나가 정확하게

에러가 발생한 어드레스를 가리킵니다.

그리고, 현재의 스택 포인터와 이전의 스택 포인터를 가진 스택 프레임 포인터 값을 구해서

차례로 이전 스택까지 내려가시면 됩니다.

건승하시길.

고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.

고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.

twins99의 이미지

해당 내용을 공부할 수 있는 site나 정보 있으시면 공유 부탁드립니다.

쉽지 않은 작업일 줄 알고 있습니다만, 한번 공부해 보고 싶네요.

답변 감사드립니다.

익명사용자의 이미지

의심가는 지역에 printf("%d ",cnt++); 를 집어 넣으셔요 -_-
'급한' 프로젝트 라면요.
물론 디버거 쓰는게 최고지만
제 임베디드 보드는 메모리가 마니 부족해서 objdump 나 gdb 를 미처 넣지 못했어서
썻던 가슴시린 방법입니다..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.