如何限制32位应用程序在64位Linux上的地址space为3GB?

How to limit the address space of 32bit application on 64bit Linux to 3GB?

是否可以让 64 位 Linux 加载程序将加载的 32 位程序的地址 space 限制在某个上限?

或者在地址space中设置一些空洞不被内核分配?

我的意思是针对特定的可执行文件,而不是针对所有进程全局,也不是​​通过内核配置。一些代码或 ELF 可执行标志是适当解决方案的示例。

对于所有加载的共享库也应该强制限制。

澄清:

我要解决的问题是我的代码使用 0xc0000000 以上的数字作为句柄值,我想清楚地区分句柄值和内存地址,即使内存地址是由第三方分配和返回的库函数。

只要64位Linux中的地址space非常接近4G限制,就没有足够的寻址space留给句柄值。

另一方面,3GB 甚至更少足以满足我的所有需求。

好的,我在别处找到了这个问题的答案。

解决方案是将程序的 "personality" 更改为 PER_LINUX32_3GB,使用 Linux 系统调用 sys_personality。

但是有个问题。切换到 PER_LINUX32_3GB Linux 后,内核将不会在上层 1GB 中分配 space,但是已经分配的 space,例如应用程序堆栈,仍然保留在那里。

解决方法是"restart"你的程序通过sys_execve系统调用。

这是我将所有内容打包在一起的代码:

proc ___SwitchLinuxTo3GB
begin
        cmp     esp, $c0000000
        jb      .finish                 ; the system is native 32bit

; check the current personality.

        mov     eax, sys_personality
        mov     ebx, -1
        int     

; and exit if it is what intended

        test    eax, ADDR_LIMIT_3GB
        jnz     .finish                         ; everything is OK.

; set the needed personality

        mov     eax, sys_personality
        mov     ebx, PER_LINUX32_3GB
        int     

; and restart the process

        mov     eax, [esp+4]          ; argument count
        mov     ebx, [esp+8]          ; the filename of the executable.
        lea     ecx, [esp+8]          ; the arguments list.
        lea     edx, [ecx+4*eax+4]    ; the environment list.

        mov     eax, sys_execve
        int     

        ; if something gone wrong, it comes here and stops!
        int3

.finish:
        return
endp