리눅스 시스템 호출 흐름도
Application Program
1. Read(fd, buffer, count);
2. glib wrapper funciton
read(...){
syscall(SYS_read,fd,buff,count),
...
}
3. Trap Handler
system_call
---
---
---
4. System call Service routine
SYS_read(){
---
---
return error
}
응답은 역순
4. System call Service routine
SYS_read(){
---
---
return error
}
3. Trap Handler
system_call
---
---
---
2. glib wrapper funciton
read(...){
syscall(SYS_read,fd,buff,count),
...
}
1. Read(fd, buffer, count);
Compile
=========
Source code file(S)
gcc -E hello.c 1> hello.i
Preprocessed code file(s)
gcc -S hello.i
Assembly code(s)
gcc -c hello.s
Linked(ld)
gcc -hello.o -o myexe
Executable file (myexe)
특정 형식의 실행 가능 이미지로 2 차 저장소에 저장
Loader
Process Address Space in main memory
메인 메모리의 주소 공간 처리
버전 확인.
shell> gcc --version
hellow.c
shell> cat hellow.c
#include <stdio.h>
int main(){
printf("Welcome to system Programming with Korea HeaNam...\n");
return 0;
}
compile: 전처리 정보 확인 컴파일
shell> gcc -E hellow.c 1> hello.i
생성된 파일 확인
shell> less hello.i
전처리 위치
shell> ls /usr/include
어셈블러 버전 지정 컴파일
shell> gcc -S hello.i -std=c11
-std=c11 버전 확인
shell> man 7 standards
디버깅 활성화 컴파일
shell> gcc -c -ggdb hello.s
hello.o 오브젝트 파일 생성.
라이브러리 확인
shell> man 7 libc
cd /usr/lib/x86_64-linux-gnu
동적 라이브 러리 검색
shell> ls | grep libc.so
정적 라이브 러리 검색
shell> ls | grep libc.a
printf 라이브 러리 확인
shell> ar -t libc.a | grep printf.o
실행 파일 동적 라이브러리 사용 생성 -lc==lib c 기본 경로 연결
shell> gcc hello.c -o dynamicexe -lc
실행 파일 정적 라이브러리 사용 생성 --static
shell> gcc hello.c -o staticexe -lc --static
크기 확인
shell> ls -lh dynamicexe staticexe
-rwxrwxr-x 1 linuxlee linuxlee 8.2K 12월 9 23:13 dynamicexe
-rwxrwxr-x 1 linuxlee linuxlee 825K 12월 9 23:13 staticexe
오브젝트 파일 형식 분석
======================
오브젝트 elf 파일 형식 -h 헤더 내용 추출
shell> readelf -h hello.o
오브텍트 elf 파일 형식 -a 전체 내용 추출
shell> readelf -a hello.o
오브텍트 elf 파일 형식 -S 섹션 내용 추출
shell> readelf -S hello.o
헤더 덤프
shell> objdump -h hello.o
디버그 덤프
shell> objdump -D hello.o
가단하게 덤프
shell> objdump -d hello.o
머신 지정 덤프
shell> objdump -d -M intel hello.o
gdb
===
shell> gcc -ggdb hello.c
shell> gdb -q ./a.out
메인 세션 어셈블러 확인
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000000063a <+0>: push %rbp
0x000000000000063b <+1>: mov %rsp,%rbp
0x000000000000063e <+4>: lea 0xa3(%rip),%rdi # 0x6e8
0x0000000000000645 <+11>: callq 0x510 <puts@plt>
0x000000000000064a <+16>: mov $0x0,%eax
0x000000000000064f <+21>: pop %rbp
0x0000000000000650 <+22>: retq
End of assembler dump.
머신 CPU 지정 어셈블러 확인
(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000000063a <+0>: push rbp
0x000000000000063b <+1>: mov rbp,rsp
0x000000000000063e <+4>: lea rdi,[rip+0xa3] # 0x6e8
0x0000000000000645 <+11>: call 0x510 <puts@plt>
0x000000000000064a <+16>: mov eax,0x0
0x000000000000064f <+21>: pop rbp
0x0000000000000650 <+22>: ret
End of assembler dump.
레지스터 확인
(gdb) break main
Breakpoint 1 at 0x63e: file hello.c, line 4.
(gdb) run
Starting program: /home/linuxlee/language/systemprogramming/01/a.out
Breakpoint 1, main () at hello.c:4
4 printf("Welcome to system Programming with Korea HeaNam...\n");
(gdb) info registers
rax 0x55555555463a 93824992233018
rbx 0x0 0
rcx 0x555555554660 93824992233056
rdx 0x7fffffffdc98 140737488346264
rsi 0x7fffffffdc88 140737488346248
rdi 0x1 1
rbp 0x7fffffffdba0 0x7fffffffdba0
rsp 0x7fffffffdba0 0x7fffffffdba0
r8 0x7ffff7dd0d80 140737351847296
r9 0x7ffff7dd0d80 140737351847296
r10 0x2 2
r11 0x3 3
r12 0x555555554530 93824992232752
r13 0x7fffffffdc80 140737488346240
r14 0x0 0
r15 0x0 0
rip 0x55555555463e 0x55555555463e <main+4>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
전체 레지스터 확인(실수 연산 확인)
(gdb) info all-registers
(gdb) c
Continuing.
Welcome to system Programming with Korea HeaNam...
[Inferior 1 (process 22554) exited normally]
(gdb) q
메모리 맵 확인
shell> readelf -h hello.o
shell> readelf -S hello.o
시스템 콜 프로그램
==============
1:일반 명령어
2:시스템 호출
3:C 표준 라이브러리 함수들
4:특수 파일 (보통 /dev 에서 발견되는 장치 파일)과 드라이버
5:파일 형식과 convensions
6:게임과 화면 보호기
7:기타
8:시스템 관리 명령어와 데몬
시스템 콜 맨 페이지
man 2 intro
man syscalls
man 2 write
기본 함수 사용 시스템 콜
======================
shell> vi wrapper_lee.c
#include <unistd.h>
int main(void){
char str[] = {"Welcome to System Programming with Korea HeaNam...\n"};
int rv = write(1, str, sizeof str);
return rv;
}
shell> gcc wrapper_lee.c
./a.out
Welcome to System Programming with Korea HeaNam...
shell> echo $?
52
소스 코드 return rv; 를 돌려준 값이다.
syscall 함수 사용
===================
shell> man 2 sycall
x86-64 rdi rsi rdx r10 r8 r9 -
shell> less /usr/include/x86_64-linux-gnu/asm/unistd_64.h
shell> cat syscall.c
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main(void){
char str[]={"Welcome to System Programming with Korea HeaNam...\n"};
int rv = syscall(1, 1, str, sizeof str);
return rv;
}
shell> gcc syscall.c
shell> a.out
Welcome to System Programming with Korea HeaNam...
shell> echo $?
52
assembly system write call
===========================
shell> gcc -o syscall.c
shell> ./a.out
shell> echo $?
52
cat syscall.nasm
global main
SECTION .data
msg: db "Welcome to System Programming with Korea HeaNam...", 0Ah, 0h
len_msg: equ $ - msg
SECTION .text
main:
mov rax,1
mov rdi,1
mov rsi,msg
mov rdx,len_msg
syscall ; write(1, msg, len_msg);
mov r15, rax
mov rax,60
mov rdi,r15
syscall ; exit(52)
shell> nasm -f elf64 syscall.nasm
shell> ld syscall.o -o myexe1
shell> myexe1
Welcome to System Programming with Korea HeaNam...
shell> echo $?
52