gpt4 book ai didi

c - 编译 glibc 时 mipsel-gcc 产生的奇怪加载指令

转载 作者:太空宇宙 更新时间:2023-11-03 23:46:56 25 4
gpt4 key购买 nike

我正在尝试让一小段 hello-world MIPS 程序在 Gem 5 模拟器中运行。该程序使用 gcc 4.9.2 和 glibc 2.19(由 crosstool-ng 构建)编译,在 qemu 中运行良好,但在 gem5 中因页面错误(试图访问地址 0)而崩溃。

代码很简单:

#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}

文件./test 结果:

./test: ELF 32-bit LSB executable, MIPS, MIPS-I version 1, statically linked, for GNU/Linux 3.15.4, not stripped

用gdb 调试后,我发现页面错误是由glibc 中的_dl_setup_stack_chk_guard 函数触发的。它接受由 __libc_start_main 函数传递的名为 _dl_random 的空指针,该指针恰好为 NULL。然而,据我所知,这些函数从不取消引用指针,而是生成指令以从 _dl_random 指针指向的内存中加载值。一些代码片段可能有助于理解:

在函数 __libc_start_main 中(宏 THREAD_SET_STACK_GUARD 未设置):

   /* Initialize the thread library at least a bit since the libgcc
functions are using thread functions if these are available and
we need to setup errno. */
__pthread_initialize_minimal ();

/* Set up the stack checker's canary. */
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARD
THREAD_SET_STACK_GUARD (stack_chk_guard);
# else
__stack_chk_guard = stack_chk_guard;
# endif

在函数 _dl_setup_stack_chk_guard 中(始终内联):

static inline uintptr_t __attribute__ ((always_inline))
_dl_setup_stack_chk_guard (void *dl_random)
{
union
{
uintptr_t num;
unsigned char bytes[sizeof (uintptr_t)];
} ret = { 0 };

if (dl_random == NULL)
{
ret.bytes[sizeof (ret) - 1] = 255;
ret.bytes[sizeof (ret) - 2] = '\n';
}
else
{
memcpy (ret.bytes, dl_random, sizeof (ret));
#if BYTE_ORDER == LITTLE_ENDIAN
ret.num &= ~(uintptr_t) 0xff;
#elif BYTE_ORDER == BIG_ENDIAN
ret.num &= ~((uintptr_t) 0xff << (8 * (sizeof (ret) - 1)));
#else
# error "BYTE_ORDER unknown"
#endif
}
return ret.num;
}

反汇编代码:

   0x00400ea4 <+228>:   jal 0x4014b4 <__pthread_initialize_minimal>
0x00400ea8 <+232>: nop
0x00400eac <+236>: lui v0,0x4a
0x00400eb0 <+240>: lw v0,6232(v0)
0x00400eb4 <+244>: li a0,-256
0x00400eb8 <+248>: lwl v1,3(v0)
0x00400ebc <+252>: lwr v1,0(v0)
0x00400ec0 <+256>: addiu v0,v0,4
0x00400ec4 <+260>: and v1,v1,a0
0x00400ec8 <+264>: lui a0,0x4a
0x00400ecc <+268>: sw v1,6228(a0)
  • 0x4a1858 (0x4a0000 + 6232)_dl_random的地址
  • 0x4a1854 (0x4a0000 + 6228)__stack_chk_guard的地址

页面错误发生在 0x00400eb8。我不太明白指令 0x00400eb80x00400ebc 是如何生成的。有人可以解释一下吗?谢谢。

最佳答案

下面是我如何找到这个问题的根源以及我的解决方案建议。

我认为深入了解 the Glibc source code 很有帮助看看到底发生了什么。从 _dl_random 开始或 __libc_start_main都可以。

作为_dl_random的值出乎意料的是 NULL,我们需要找到这个变量是如何初始化和 where it is assigned .借助代码分析工具,我们可以找到_dl_random。在 Glibc 中仅在函数 _dl_aux_init 中分配有意义的值,并且此函数由 __libc_start_min 调用.

_dl_aux_init迭代其参数 -- auxvec -- 和对应于 auxvec[i].at_type 的行为. AT_RANDOM _dl_random 的分配就是这种情况.所以问题是没有 AT_RANDOM制作元素 _dl_random已分配。

由于程序在用户态qemu下运行良好,问题的根源在于系统环境提供者,比如说gem5,它负责构建auxvec。 .有了那个关键字,我们可以找到 auxv build 于 gem5/src/arch/<arch-name>/process.cc .

当前auxv MIPS 的构造如下:

    // Set the system page size
auxv.push_back(auxv_t(M5_AT_PAGESZ, MipsISA::PageBytes));
// Set the frequency at which time() increments
auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
// For statically linked executables, this is the virtual
// address of the program header tables if they appear in the
// executable image.
auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable());
// This is the size of a program header entry from the elf file.
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
// This is the number of program headers from the original elf file.
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
//The entry point to the program
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
//Different user and group IDs
auxv.push_back(auxv_t(M5_AT_UID, uid()));
auxv.push_back(auxv_t(M5_AT_EUID, euid()));
auxv.push_back(auxv_t(M5_AT_GID, gid()));
auxv.push_back(auxv_t(M5_AT_EGID, egid()));

现在我们知道该怎么做了。我们只需要为 _dl_random 提供一个可访问的地址值标记为 MT_AT_RANDOM . Gem5 的 ARM arch 已经实现了这一点 ( code )。或许我们可以举个例子。

关于c - 编译 glibc 时 mipsel-gcc 产生的奇怪加载指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30285658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com