카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2018/12/10

Linux system programming 시스템 콜

리눅스 시스템 호출 흐름도

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