본문 바로가기

Programming/Linux_Kernel

arm 에서 system call 을 호출할때 4개 이상의 파라미터를 어떻게 처리하는가?


다음과 같이 arm 컴파일러를 지정해 주면 arm 용으로 컴파일이 가능하다.

/opt/toolchains/arm-linux-4.1.1/bin/arm-linux-gcc -o test test.c

이때 -S 옵션을 주면 어셈형태의 파일이 나와서 직접 asm 파일을 볼 수 있다.

/opt/toolchains/arm-linux-4.1.1/bin/arm-linux-gcc -S test.c


다음과 같이 파라미터가 6개인 sendto system call 에 가상으로 파라미터들을 넣어서 추적해 보았다.

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>

 

int main()
{
 int _s=0x11;
 void *_msg = (void*)0x22;
 size_t _len = 0x33;
 int _flags = 0x44;
 struct sockaddr* _to = (struct sockaddr*)0x55;
 socklen_t _tolen = 0x66;

 printf("Hello World~!!\n");

    // int sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

 sendto(_s, _msg, _len, _flags, _to, _tolen); 

 printf("program end~!\n");

 return 0;
}


각 6개의 파라미터 0x11~0x66 까지를 저장시켰다.


GLIBC의 sendto 함수를 호출하기 직전..
arm 레지스터 r0--r3 까지 4개의 파라미터가 들어가 있고,
스택에 5, 6 번째 파라미터가 들어가 있는것을 확인할 수 있다.


GLIBC 에서 SWI 를 통해서 system call 을 호출하기 바로 직전 모습
r0--r5 까지를 파라미터를 전달하는 공간으로 사용하고 있다.
user register 이다.


swi 로 go 를 하면 바로 kernel 모드인 super 모드로 변경된다.

결론 :
ARM 에서 system call을 호출할때는 일반 function call 과는 다르게 파라미터를 넘기기 위해서 user register 를 4개 이상 사용한다.
(strace 코드를 보면 18개 까지 모두 사용가능한 듯 하다.)
이는 EABI 문서를 통해 좀 더 정확히 알 수 있을듯 하다.