【问题标题】:aarch64-elf-g++ -fPIC gives different values for local and global symbolaarch64-elf-g++ -fPIC 为局部和全局符号提供不同的值
【发布时间】:2018-03-05 04:22:12
【问题描述】:

windows 10下,使用linaro提供的交叉编译工具链,全名gcc-linaro-7.2.1-2017.11-i686-mingw32_aarch64-elf(可上网搜索),编译如下代码sn-p:

// file test.cpp

// ASM_DEFINE_LOCAL_SYM and ASM_DEFINE_GLOBAL_SYM defines assembler symbol,
// one is local and the other is global, as their name indicated
#define ASM_DEFINE_LOCAL_SYM(sym) __asm__ __volatile__(#sym ":\n\t")
#define ASM_DEFINE_GLOBAL_SYM(sym) __asm__ __volatile__(".global " #sym " \n\t;" #sym ":\n\t")

void testIfLocalSymWrongs()
{
    kout << "func address = " <<reinterpret_cast<uint64_t>(testIfLocalSymWrongs) << "\n";
    extern char local[];
    extern char global[];

    ASM_DEFINE_LOCAL_SYM(local);
    ASM_DEFINE_GLOBAL_SYM(global);
    kout << "local = " << reinterpret_cast<uint64_t>(local) << "\n";
    kout << "global = " << reinterpret_cast<uint64_t>(global) << "\n";
}

代码不完整,因为我正在裸机环境中测试迷你内核。在上面的代码中,kout 只是将字符写入串行端口(当使用像raspberry pi 3 这样的硬件时)或控制台(当使用模拟器,例如QEMU),但我认为它不需要是完整的。 不管怎样,编译命令是aarch64-elf-g++ -fPIC test.cpp .... -o test,使用aarch64-elf-objcopy生成kernel.test.img,其中只包含二进制代码,其他数据如elf头被剥离。

在 QEMU 上运行它:qemu-system-aarch64 -machine virt,gic-version=3 -cpu cortex-a53 -smp 1 -m 1G -nographic -serial stdio -bios kernel.test.img 给出以下输出:

func address = 3c64
local = 3c64
global = 3cc0

而您可以看到func addresslocal 相同,而localglobal 不同,这与我们的预期完全不同。

核心问题是当你使用-fPIC编译时,局部符号和全局符号本应相同时却有不同的值。

也许aarch64-elf-g++ 生成了错误的.got 部分?但我不确定,谁能解释一下?

【问题讨论】:

    标签: g++ arm64 fpic


    【解决方案1】:

    一天后解决了这个问题,抱歉这么晚才回答。 这是编译选项-fPIC-pie 之间的区别,当您使用后者替换前者时,程序将给出正确的(如预期的)输出。

    因此,当使用像aarch64-elf-g++ 这样的交叉工具链进行编译以生成position independent code 时,您更喜欢-pie 而不是-fPIC

    请自行测试,如果可能,请回复此答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      相关资源
      最近更新 更多