Bash 스크립트에서 GDB를 사용하는 프로세스의 메모리 덤프 - 오류, 문제

Bash 스크립트에서 GDB를 사용하는 프로세스의 메모리 덤프 - 오류, 문제

특정 프로그램의 메모리 세그먼트를 파일로 덤프하고 싶습니다. 내 프로그램은 밀리초 단위로 작동하므로 다음을 사용합니다.명명된 파이프실행을 중지하고 gdb동시에 메모리 내용을 덤프합니다. 스크립트는 어떤 경우에는 작동하지만 다른 경우에는 작동하지 않습니다. 출력을 일부 필터로 리디렉션하여 형식을 지정하려고 할 때 , --nw옵션을 추가하면 오류가 발생합니다.--nh

질문:--nw이러한 오류의 원인은 무엇이며 추가된 옵션을 사용하도록 스크립트를 가져올 수 없는 이유는 무엇입니까 --nh?

간단한 예를 통해 이를 보여드리겠습니다.

내 프로그램.c

#include <stdio.h>

int main() {
    puts("one two three");
    return 0;
}

스크립트 파일

function find_stack_addr {
    read stack_start stack_end <<< $(awk '
    /\[stack\]/ {split($1, stack_maps, "-")}

    END {
        stack_start = "0x" stack_maps[1]
        stack_end = "0x" stack_maps[2]

        print stack_start, stack_end
    }' $1)
}

function dump_mem {
    ./my_program y y y > named_pipe &
    pid=$!

    find_stack_addr "/proc/${pid}/maps"

    sudo gdb --batch --pid "$pid" -ex "dump memory dumps/stack_${1}.dump $stack_start $stack_end"
    echo "$pid $stack_start $stack_end"
}

mkfifo named_pipe

for i in {1..3}; do
   dump_mem "$i"
done

rm named_pipe

결과

12798 0x7ffc5a875000 0x7ffc5a896000
12806 0x7ffc5a875000 0x7ffc5a896000
12814 0x7ffc5a875000 0x7ffc5a896000

그리고

dumps/
├── stack_1.dump
├── stack_2.dump
└── stack_3.dump

for루프 출력을 column헤더가 추가된 프로그램 으로 리디렉션 하고 싶었기 때문에 for루프를 다음과 같이 변경했습니다.

for i in {1..3}; do
   dump_mem "$i"
done | sed '1  i\pid stack_start stack_end' | column -t

오류가 발생했습니다(스크립트도 완료되지 않았습니다).

/home/minimax/.gdbinit:4: Error in sourced command file:
Cannot enable the TUI when output is not a terminal
47  ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.

stdin내 파일 설정 이 아닌 파이프로 리디렉션하여 문제가 발생한 것이 분명했기 .gdbinit때문에 명령에 두 가지 옵션을 추가했습니다 gdb.

  --nh               Do not read ~/.gdbinit.
  --nw               Do not use the GUI interface.

이제 gdb명령은 다음과 같습니다.

sudo gdb --nw --nh --batch --pid "$pid" -ex "dump memory dumps/stack_${1}.dump $stack_start $stack_end"

그런 다음 TUI오류가 사라졌지만 다음 No such file or directory은 아닙니다.

47  ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.
47  ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.
47  ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.

forgdb첫 번째 루프에 대해 이 명령(옵션 추가)을 사용해 보았지만 --nw --nh스크립트가 작동하고 결과가 에코되었지만 오류도 발생했습니다.

0x00007f4dab824d9e in __libc_open64 (file=0x55da21e2e9a0 "named_pipe", oflag=577) at ../sysdeps/unix/sysv/linux/open64.c:47
47  ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.
13130 0x7ffcada58000 0x7ffcada79000      #<--- the script's output

답변1

해결 방법을 찾았습니다 . GDB의 출력을 리디렉션합니다 /dev/stdout. 논리는 다음과 같습니다. GDB출력이 터미널에 연결되어 있을 때 제대로 작동하면 이 연결을 제공해야 합니다. 이 경우에는 오류가 없습니다.

제 경우에는 /dev/stdout다음을 가리킵니다 /dev/pts.

$ ls -l /dev/stdout 
lrwxrwxrwx 1 root root 15 Oct  9 10:10 /dev/stdout -> /proc/self/fd/1

$ ls -l /proc/self/fd/1
lrwx------ 1 minimax minimax 64 Oct  9 15:00 /proc/self/fd/1 -> /dev/pts/11

고정 코드

function dump_mem {
    ./my_program y y y > named_pipe &
    pid=$!

    find_stack_addr "/proc/${pid}/maps"

    sudo gdb --batch --pid "$pid" -ex "dump memory dumps/stack_${1}.dump $stack_start $stack_end" > /dev/stdout

    echo "$pid $stack_start $stack_end"
    cat named_pipe > /dev/null
}

관련 정보