简短的答案似乎是没有简单的答案。至少没有简单的方法来重新分配堆栈指针的范围/位置。
加载器“ld-linux.so”在进程激活的早期阶段获取 hurd 加载器中的地址 - 在 glibc 源代码 elf/ 和 sysdeps/x86_64/ 中搜索 elf_machine_load_address() 和 elf_machine_runtime_setup()。
这发生在调用您的 _start() 条目和相关设置以调用您的 main() 的序言中,不适合胆小的人,即使我无法说服自己这是一条安全的路线。
当它发生时 - 解决方案以其他一些老派的技巧出现......指针通货紧缩/通货膨胀......
如果使用 -mcmodel=small,那么自动变量、alloca() 地址以及 argv[] 和 envp 之类的东西都是从高内存分配的,堆栈将从高内存向下增长。这些地址在此示例代码中得到验证:
#include <stdlib.h>
#include <stdio.h>
#include <alloca.h>
extern char etext, edata, end;
char global_buffer[128];
int main( int argc, const char *argv[], const char *envp )
{
char stack_buffer[128];
static char static_buffer[128];
char *cp = malloc( 128 );
char *ap = alloca( 128 );
char *xp = "STRING CONSTANT";
printf("argv[0] %p\n",argv[0]);
printf("envp %p\n",envp);
printf("stack %p\n",stack_buffer);
printf("global %p\n",global_buffer);
printf("static %p\n",static_buffer);
printf("malloc %p\n",cp);
printf("alloca %p\n",ap);
printf("const %p\n",xp);
printf("printf %p\n",printf);
printf("First address past:\n");
printf(" program text (etext) %p\n", &etext);
printf(" initialized data (edata) %p\n", &edata);
printf(" uninitialized data (end) %p\n", &end);
}
产生这个输出:
argv[0] 0x7fff1e5e7d99
环境 0x7fff1e5e6c18
堆栈 0x7fff1e5e6a80
全局 0x6010e0
静态0x601060
malloc 0x602010
分配 0x7fff1e5e69d0
常量 0x400850
printf 0x4004b0
过去的第一个地址:
程序文本 (etext) 0x400846
初始化数据(eddata)0x601030
未初始化数据(结束)0x601160
对结构的 32 位部分的所有访问都必须使用 inflate() 和 deflate() 例程进行包装,例如:
void *inflate( unsigned long );
unsigned int deflate( void *);
deflate() 测试设置在 0x7fff00000000 范围内的位并标记指针,以便 inflate() 识别如何重构实际指针。
如果有人同样必须支持 64 位指针的 32 位存储结构,希望对您有所帮助。