728x90
error 처리
외부 함수인 ___error를 사용해서 errno 값을 세팅
errno는 가장 최근 에러의 번호를 담는 integer 타입 변수이다.
- 프로그램이 시작되면 errno는 0으로 초기화 된다
- 에러가 생기면 시스템 콜 함수는 NULL 또는 -1을 반환한다
- 에러 타입을 파악하기 위해 외부 변수 errno에 에러 번호가 담긴다
man errno
/*
...
When a system call detects an error, it returns an integer value indicating failure (usually -1) and sets the variable errno accordingly. <This allows interpretation of the failure on receiving a -1 and to take action accordingly.> Successful calls never set errno; once set, it remains until another error occurs.
...
0 Error 0. Not used.
1 EPERM Operation not permitted. An attempt was made to perform an operation limited to processes with appropriate privileges or to the owner of a file or other resources.
2 ENOENT No such file or directory. A component of a specified pathname did not exist, or the pathname was an empty string.
...
*/
___error() 함수란?
errno의 주소를 리턴하는 함수
// /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/errno.h
extern int * __error(void);
#define errno (*__error())
errno에 에러번호를 세팅하려면 errno의 주소가 필요하다. (___error의 리턴값)
- FreeBSD에서는 시스템콜이 errno를 세팅하는 대신 errno를 바로 리턴하고 carry flag를 1로 바꿔준다.
- FreeBSD는 정통 유닉스 운영체제이며 MacOS X의 일부가 FreeBSD를 바탕으로 개발되었다.
- 때문에 Mac OS X 를 사용하는 컴퓨터에서는 시스템 콜 에러시 직접 시스템 콜의 리턴값을 -1로 세팅하고 변수 errno에 에러 넘버를 세팅해주어야 한다.
- write, read 함수의 메뉴얼
- Otherwise, a -1 is returned and the global variable errno is set to indicate the error.
___error() 사용법
- write 함수에서 에러가 발생하면 carry flag가 1로 바뀌고 rax에 에러 넘버가 저장된다.
- syscall 함수에서 반환된 값(반환 값이므로 RAX에 저장)을 다른 레지스터 혹은 스택에 저장해둔다.
- ___error를 호출하면 rax의 에러 넘버를 확인하고 errno의 주소를 반환하여 rax에 저장한다.
- 스택 혹은 다른 레지스터에 저장되었던 errno를 rdx에 넣어준다.
- 반환된 주소값이 있는 rax가 가리키는 곳에 스택 혹은 레지스터에 담아둔 errno를 넣어준다
- rax 에 -1을 넣어 반환한다.
728x90
300x250