42Seoul/Libasm

[Libasm] syscall error 처리

  • -
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
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.