특정 프로그램의 메모리 세그먼트를 파일로 덤프하고 싶습니다. 내 프로그램은 밀리초 단위로 작동하므로 다음을 사용합니다.명명된 파이프실행을 중지하고 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.
for
gdb
첫 번째 루프에 대해 이 명령(옵션 추가)을 사용해 보았지만 --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
}