최소 실행 가능 예
개념이 명확하지 않으면 설명하지 않은 더 간단한 예가 있습니다.
이 경우 그 예는 Linux x86_64 어셈블리 독립형 (libc 없음) hello world입니다.
안녕하세요 .S
.text
.global _start
_start:
/* write */
mov $1, %rax /* syscall number */
mov $1, %rdi /* stdout */
mov $msg, %rsi /* buffer */
mov $len, %rdx /* buffer len */
syscall
/* exit */
mov $60, %rax /* exit status */
mov $0, %rdi /* syscall number */
syscall
msg:
.ascii "hello\n"
len = . - msg
GitHub의 상류 .
조립 및 실행 :
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
예상 결과를 출력합니다.
hello
이제이 예제에서 strace를 사용하겠습니다 :
env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log
우리는 사용:
strace.log
이제는 다음을 포함합니다 :
execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6) = 6
exit(0) = ?
+++ exited with 0 +++
이러한 최소한의 예를 통해 출력의 모든 단일 문자는 자명합니다.
execve
line : CLI 인수 및 환경을 포함하여 strace
실행 방법을 보여줍니다 hello.out
.man execve
write
line : 우리가 작성한 쓰기 시스템 호출을 보여줍니다. 6
문자열의 길이입니다 "hello\n"
.
= 6
시스템 호출의 리턴 값이며, 문서화 된 man 2 write
바이트 수입니다.
exit
line : 우리가 만든 엑시트 시스템 호출을 보여줍니다. 프로그램이 종료되었으므로 리턴 값이 없습니다!
더 복잡한 예
strace의 응용 프로그램은 복잡한 프로그램이 실제로 프로그램을 디버그 / 최적화하기 위해 수행하는 시스템 호출을 확인하는 것입니다.
특히 Linux에서 발생할 가능성이있는 대부분의 시스템 호출에는 glibc 래퍼가 있으며 그 중 대부분은 POSIX에서 제공 됩니다.
내부적으로 glibc 래퍼는 다음과 같이 인라인 어셈블리를 사용합니다. 인라인 어셈블리 에서 sysenter를 통해 시스템 호출을 호출하는 방법은 무엇입니까?
공부해야 할 다음 예는 POSIX write
hello world입니다.
main.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
char *msg = "hello\n";
write(1, msg, 6);
return 0;
}
컴파일하고 실행하십시오.
gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
이번에 main
는 main을위한 멋진 환경을 설정 하기 전에 glibc가 시스템 호출을 많이하고 있음을 알 수 있습니다.
우리는 이제 독립 프로그램을 사용하지 않고 libc 기능을 허용하는보다 일반적인 glibc 프로그램을 사용하고 있기 때문입니다.
그런 다음 모든 끝에서 다음을 strace.log
포함합니다.
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
따라서 write
POSIX 함수는 Linux write
시스템 호출을 사용합니다.
우리는 또한 대신에 전화로 return 0
연결되는 것을 관찰합니다 . 하, 나는 이것에 대해 몰랐다! 이것이 너무 멋진 이유 입니다. 그런 다음 설명 :exit_group
exit
strace
man exit_group
이 시스템 호출은 호출 스레드뿐만 아니라 호출 프로세스 스레드 그룹의 모든 스레드를 종료한다는 점을 제외하고 exit (2)와 같습니다.
그리고 여기에 어떤 시스템 호출이 dlopen
사용 되는지 연구 한 또 다른 예가 있습니다.
Ubuntu 16.04, GCC 6.4.0, Linux 커널 4.4.0에서 테스트되었습니다.