2

Gem 5 シミュレーターで実行される hello-world MIPS プログラムの一部を取得しようとしています。このプログラムは gcc 4.9.2 および glibc 2.19 (crosstool-ng によってビルド) でコンパイルされ、qemu では問題なく動作しますが、gem5 ではページ フォールト (アドレス 0 にアクセスしようとする) でクラッシュしました。

コードはかなり単純です。

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

file ./test結果:

./test: ELF 32 ビット LSB 実行可能ファイル、MIPS、MIPS-I バージョン 1、静的にリンク、GNU/Linux 3.15.4 用、削除されていない

gdb でデバッグした後、ページ フォールトが_dl_setup_stack_chk_guardglibc の関数によってトリガーされていることがわかりました。これは、関数_dl_randomによって渡されるvoid ポインターを受け入れます。ただし、私の知る限り、これらの関数はポインターを逆参照することはありませんが、メモリポインターが指すメモリから値をロードする命令が生成されました。一部のコードは理解に役立つ場合があります。__libc_start_mainNULL_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

でページ フォールトが発生しました0x00400eb80x00400eb8命令と0x00400ebc生成方法がよくわかりません。誰かがそれに光を当てることができますか?ありがとう。

4

1 に答える 1