특히 큰(~10^6 LOC) 프로그램으로 인해 내 stty 설정이 에서 로 변경되었으며 echo ixon icanon
, -echo -ixon -icanon
이 변경을 초래하는 이 큰 프로그램에서 함수를 찾고 싶습니다.
나는 분명히 이 엉망인 OOP 스파게티 코드를 통해 실행을 추적하고 싶지 않습니다.
stty 설정을 모니터링하고 변경 사항을 기록하는 방법은 무엇입니까? strace
나는 내가 필요한 정보를 제공할 수 있을 것이라고 생각 awk
하지만 어떤 시스템 호출을 필터링해야 할지 모르겠습니다.
답변1
특정 작업이나 상호 작용에 의해 이벤트가 발생할 수 있다고 생각하는 경우 가장 쉬운 방법은 다음과 같습니다.
watch -d -n1 "stty -F /dev/pts/106 -a | grep -Eo '.(icanon|ixon)'"
새 터미널에서 실행하세요. 옵션은 -F
프로그램을 실행할 터미널입니다( tty
실행하기 전에 실행하여 프로그램이 무엇인지 확인하세요). | grep ..
전체 터미널 상태를 관찰하려면 생략하세요.
Linux를 사용하는 경우 다음 옵션은 다음을 사용하는 것입니다.ltrace
라이브러리 호출 추적은 비슷하지만 strace
(일부 기능 포함 strace
) 커널 시스템 호출뿐만 아니라 사용자 공간 라이브러리에서도 작동합니다.
ltrace -tt -e tcgetattr+tcsetattr myprogram ...
tcgetattr()
그러면 터미널 속성을 가져오고 설정하기 위한 libc 함수 및 함수에 대한 타임스탬프 호출이 표시되고 추가됩니다 .tcsetattr()
ioctl()
궁극적으로 이러한 libc 호출은 또는 를 사용하여 추적 할 수 있는 시스템 호출을 사용합니다. strace
Linux에서 이를 수행하는 방법은 다음과 같습니다 truss
.strace
strace -tt -e trace=ioctl myprogram [...]
여기서 큰 장점은 strace
다양한 매개변수를 시스템 호출로 디코딩해 준다는 것입니다.
위의 어느 것도 프로그램에서 문제가 발생할 수 있는 위치를 논리적으로 알려주지 않으며, 디버거 또는 DLL 삽입이라는 두 가지 옵션이 있습니다.
쉽게 gdb
중단점을 설정 tcsetattr()
한 다음 호출 스택을 검사할 수 있지만 호출이 많으면 지루할 수 있습니다.libc의 빌드 또는 기호 디버그최상의 결과를 얻으려면).
가장 포괄적인 옵션(대상 프로그램이 동적으로 링크되어 있다고 가정)은 추적해야 하는 기능을 가로채거나 래핑하는 자체 DLL을 삽입하는 것입니다 tcsetattr()
.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <termios.h>
/*
* gcc -nostartfiles -shared -ldl -Wl,-soname,tcsetattr -o tc.so wraptc.c
* LD_PRELOAD=./tc.so stty -icanon ixon
*
*/
#define DEBUG 1
#define dfprintf(fmt, ...) \
do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
__FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
typedef int tcsetattr_fp(int fd, int optional_actions,
const struct termios *termios_p);
static tcsetattr_fp *real_tcsetattr;
void _init()
{
dfprintf("It's alive!\n","");
real_tcsetattr = dlsym(RTLD_NEXT, "tcsetattr");
dfprintf("Hooked %p tcsetattr()\n",(void *)real_tcsetattr);
}
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
{
void *bt[20];
size_t btsz;
int rc,stacktr=0;
dfprintf("Caught tcsetattr(%i,%04x,...)\n",fd,optional_actions);
if ( (fd==0) && !((termios_p->c_lflag) & ICANON)) {
dfprintf("ICANON off!\n","");
stacktr=1;
}
if ( (fd==0) && !((termios_p->c_iflag) & IXON)) {
dfprintf("IXON off!\n","");
stacktr=1;
}
if (stacktr) {
btsz=backtrace(bt,sizeof(bt));
backtrace_symbols_fd(bt,btsz,STDERR_FILENO);
}
rc=real_tcsetattr(fd,optional_actions, termios_p);
return rc;
}
주석에 지시된 대로 컴파일하고 호출하십시오. 이 코드는 실제 libc tcsetattr()
함수를 찾고 대체 버전을 포함합니다. 이 코드는 backtrace()
FD 0에서 잠재적으로 흥미로운 활동을 발견한 다음 실제 libc 버전을 호출할 때 호출됩니다. 약간의 조정이 필요할 수 있습니다.