我想编译C代码就像它是32位应用程序(所以sizeof(void *)将是4),但在64位应用程序内运行它。
我可以保证这个代码不会收到指向4 GB以上的地址空间的指针
我只需要一个工具链来做到这一点。
有一个x32内存模型可用于Linux,这是32位指针的64位代码。 这似乎更适合于“不要破坏存储在unsigned int
指针的代码,请!” 用法。 但是整个应用程序应该使用这个目标来构建。
然而,在同一个进程中结合x32和x86_64代码要比x86和x86_64要困难得多,因为它不需要CPU切换模式。
我如何编译C代码为32位代码,并在64位应用程序中运行?
在Windows和Linux上,都不能在64位进程中执行32位代码。 或者反之亦然。
我找到了用Clang / LLVM做到这一点的方法。
C代码可以通过命令行转换为ARMv7-A的LLVM中间语言(LLVM IR):
clang --target=armv7a-unknown-linux-eabi -emit-llvm -S -c 32bit-arm.c
对于下面的C代码:
int sizeof_voidp(void) { return sizeof(void*); } int char_minus_one(void) { return (char) -1; }
输出IR代码将是:
target datalayout = "em:ep:32:32-i64:64-v128:64:128-n32-S64" target triple = "armv7-unknown-linux-eabi" define i32 @sizeof_voidp() #0 { ret i32 4 } define i32 @char_minus_one() #0 { ret i32 255 }
其中“目标数据布局”具有“p:32:32”,这意味着指针是32位和32位对齐的。 请注意函数sizeof_voidp()返回4,因为ARMv7-A的指针是4个字节,char_minus_one()返回255,因为“char”对于ARM是无符号的。
现在这个IR代码可以用下面的命令行转换成x86-64汇编:
llc x86.ll -march=x86-64 -o 32bit-arm.S
结果可以汇编成目标文件,然后与其他x86-64二进制文件链接。