mmap은 x32 ABI에서 어떻게 작동합니까?

mmap은 x32 ABI에서 어떻게 작동합니까?

Linux 5.0-rc5 소스 코드를 살펴보던 중 arch/x86/entry/syscalls/syscall_64.tblx32에 대한 별도의 시스템 호출 번호가 없다는 것을 발견했습니다 mmap.

그렇다면 우리가 사용자 공간에서 x32 ABI를 사용하고 있어 4GiB 이상의 매핑된 주소를 제공하지 않는다는 것을 커널이 어떻게 알 수 있을까요?

또는 일반적으로 주소를 반환할 수 있는 시스템 호출은 우리가 x32를 사용하고 있고 4GiB 이상을 반환하지 않는다는 것을 어떻게 알 수 있습니까?

답변1

x32 시스템 호출을 하려는 프로세스는 시스템 호출 번호에 비트가 설정되어 커널이 이를 구별할 수 있습니다.

syscall(2) 맨페이지에서:

[5] The x32 ABI uses the same instruction as the x86_64 ABI and  is
    used  on  the  same processors.  To differentiate between them,
    the bit mask __X32_SYSCALL_BIT is bitwise-ORed into the  system
    call  number  for  system calls under the x32 ABI.  Both system
    call tables are available though, so setting the bit is  not  a
    hard requirement.

x32는 진정한 독립형 환경이 아닙니다. x32 프로그램은 x64 시스템 호출을 수행할 수 있으며 그 반대도 마찬가지입니다. 이는 x64 및 x32와 병렬로 지원될 수도 있는 ia32 에뮬레이션과 다릅니다.

이 비트는 다음 함수를 통해 커널에서 확인됩니다 in_x32_syscall().

static inline bool in_x32_syscall(void)
{
#ifdef CONFIG_X86_X32_ABI
        if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
                return true;
#endif
        return false;
}

커널 코드가 mmap()이를 구현하는 위치를 찾는 것은 독자의 연습 과제로 남겨집니다(어렵지 않습니다). x32 바이너리의 execve()의 경우 커널은 __X32_SYSCALL_BIT저장된 레지스터(시스템 호출 번호)에 명시적으로 자체적으로 설정됩니다.RAX

답변2

다음 함수 서명을 보면 mmap:

void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);

length메모리 크기( )가 매개변수라는 것을 알 수 있습니다 size_t.

이제 size_t그것은플랫폼 종속성유형. size_t32비트 플랫폼에서는 32비트이고, 64비트 플랫폼에서는 64비트입니다.

마찬가지이다 void *. 32비트 아키텍처의 포인터는 32비트 주소입니다.

따라서 커널은 알 필요가 없으며 컴파일러는 실제로 이에 대해 관심을 갖습니다.

관련 정보