2012-01-12 4 views
9

현재 소스 또는 심볼에 액세스 할 수없는 곳에서 발생하는 까다로운 버그가 있습니다. 즉, 충돌이 발생한 곳의 명령어 및 해당 주소를 볼 수 있지만 그게 전부입니다 그것. 내가 무엇을하고 싶은지는 gdb이 상호 작용을 요구하지 않고 실행되고 모든 명령어를 표시하므로이지만 아직 수행 할 방법을 찾지 못했습니다.gdb에서 실행 된 각 어셈블리 명령어 표시

는 내가 달성을 기대하고있어이 같은 것입니다 :

(gdb) /* some command */ 
0x2818a7c0: push %ebp 
0x2818a7c1: mov %esp,%ebp 
0x2818a7c3: push %ebx 
0x2818a7c4: sub $0x4,%esp 
... 
0x28563622: mov %esi,0x0(%eax) 
Program received signal SIGSEGV, Segmentation fault. 

내가, 프로그램 카운터의 표시를 설정과 같이됩니다 해왔 :

(gdb) display/i $pc 

을 그리고 stepi 코드를 실행 :

(gdb) stepi 
1: x/i $pc 0x2818a7c0: push %ebp 

그러나 충돌은 수백 또는 t입니다. 명령의 집을 멀리두고, 여러 번 "들어가라"고 할 필요없이 각자를 (함께한다면) 함께 볼 수있는 방법을 원합니다. 또한 수동으로 수행해야하는 경우 각 명령어 사이에 (gdb) 프롬프트가 표시되는 것이 좋을 것입니다. 나는 간단히 살펴본

한 경로는 scripting이지만, 내 유일한 생각은 표시하고 (다음 명령에 대한) 또 다른 휴식 후 계속하지만 내가 commands를 사용할 수없는 한 main()에 설치하는 것입니다 commands 블록 안에 있기 때문에 상상할 수있는 방식으로 작동하지 않습니다.

중요한 경우, 저는 FreeBSD에서 일하고 있습니다.

답변

13

당신을 위해 무엇을 요구해야 다음 단순히있다 대부분의 간단한 프로그램에서도 너무 많은 명령어가 실행되었습니다.

충돌이 발생할 때까지 프로그램을 실행하고 현재 기능이 무엇인지, 누가 그것을 호출했는지, 그리고 중단 점을 적절하게 설정할 때까지 프로그램을 실행하는 것이 더 좋은 방법 일 수 있습니다.

x86에서는 완전히 제거 된 실행 파일에서도 함수 경계를 추론 할 수 있습니다.

보고 싶은 또 다른 사항은 strace/truss 출력이므로 충돌 지점 바로 앞에 어떤 시스템 호출이 있는지 확인할 수 있습니다.

0
  1. Dissassemble 바이너리
  2. 사용 IDA와 디버거를 디버깅하는 동안 개별적으로 (예를 들어, objdump를 사용) 및 목록을 참조하십시오. IMO를 훨씬 더 잘 경험할 수 있습니다.

(면책 조항 : 나는 진수 선을 위해 일) :

# not strictly required, but you'll likely want the log anyway 
(gdb) set logging on 

# ask gdb to not stop every screen-full 
(gdb) set height 0 

(gdb) while 1 
> x/i $pc 
> stepi 
> end 

그러나 디버깅이 접근 가능성이 쓸데 증명합니다 :

+0

나는 현재 FreeBSD에서 작업하고 있음을 알리기 위해 내 질문을 업데이트했다. –

+0

아, 현재 IDA는 FreeBSD 바이너리 디버깅을 지원하지 않습니다. 그러나 여전히 디스어셈블러 (Windows/Wine 또는 FreeBSD에서의 Linux 지원)로 사용할 수 있습니다. 죽은 목록을 보는 것보다 훨씬 낫습니다. –

1

파이썬 스크립팅

이 미친 아이디어를 달성하기 위해 GDB 스크립트보다 더 많은 유연성을 제공합니다.

GDB 스크립트와 마찬가지로 주요 문제는 대상 하드웨어 지원이없는 대부분의 응용 프로그램에서 너무 느릴 수 있다는 것입니다. 예를 들어 C hello world는 main부터 시작하여 겨우 60k 명령에 2 분이 걸립니다. puts 이상으로 완료하십시오.

class TraceAsm(gdb.Command): 
    def __init__(self): 
     super().__init__(
      'trace-asm', 
      gdb.COMMAND_BREAKPOINTS, 
      gdb.COMPLETE_NONE, 
      False 
     ) 
    def invoke(self, argument, from_tty): 
     argv = gdb.string_to_argv(argument) 
     if argv: 
      gdb.write('Does not take any arguments.\n') 
     else: 
      done = False 
      thread = gdb.inferiors()[0].threads()[0] 
      last_path = None 
      last_line = None 
      with open('trace.tmp', 'w') as f: 
       while thread.is_valid(): 
        frame = gdb.selected_frame() 
        sal = frame.find_sal() 
        symtab = sal.symtab 
        if symtab: 
         path = symtab.fullname() 
         line = sal.line 
        else: 
         path = None 
         line = None 
        if path != last_path: 
         f.write("path {}{}".format(path, os.linesep)) 
         last_path = path 
        if line != last_line: 
         f.write("line {}{}".format(line, os.linesep)) 
         last_line = line 
        pc = frame.pc() 
        f.write("{} {} {}".format(hex(pc), frame.architecture().disassemble(pc)[0]['asm'], os.linesep)) 
        gdb.execute('si', to_string=True) 
TraceAsm() 

샘플 출력 :

path /home/cirsan01/bak/git/cpp-cheat/c/exit.c 
line 95 
0x7ffff7318f9b add $0x8,%rbp 
0x7ffff7318f9f cmp %r12,%rbp 
0x7ffff7318fa2 jb  0x7ffff7318f98 <__run_exit_handlers+136> 
line 97 
0x7ffff7318fa4 mov %ebx,%edi 
0x7ffff7318fa6 callq 0x7ffff73ab710 <__GI__exit> 
path /build/glibc-bfm8X4/glibc-2.23/posix/../sysdeps/unix/sysv/linux/_exit.c 
line 27 
0x7ffff73ab710 movslq %edi,%rdx 
0x7ffff73ab713 mov 0x2f775e(%rip),%r9  # 0x7ffff76a2e78 
line 31 
0x7ffff73ab71a mov $0xe7,%r8d 
line 33 
0x7ffff73ab720 mov $0x3c,%esi 
0x7ffff73ab725 jmp 0x7ffff73ab740 <__GI__exit+48> 
line 31 
0x7ffff73ab740 mov %rdx,%rdi 
0x7ffff73ab743 mov %r8d,%eax 
0x7ffff73ab746 syscall 

우분투 16.04, GDB 7.11 시험. GitHub upstream.

관련 문제