3

次のコマンドを実行すると、function()
(gdb) break function()
ブレークポイント 1 の別のアドレスが function() 0x804834a に取得されます。
(gdb) print function()
function() 0x8048344 のブレークポイント 1。
両方の住所に違いがあるのはなぜですか?

4

2 に答える 2

4

この出力は正しくありません。次のようにすると、次のようになります。

int func(void) {
  int a = 10;
  printf("%d\n", a);
  return 1;
}

gdbにロードした後:

(gdb) p func
$1 = {int (void)} 0x4016b0 <func>
(gdb) b func
Breakpoint 1 at 0x4016b6: file file.c, line 4.
(gdb) disassemble func
Dump of assembler code for function func:
   0x004016b0 <+0>:     push   %ebp
   0x004016b1 <+1>:     mov    %esp,%ebp
   0x004016b3 <+3>:     sub    $0x28,%esp
   0x004016b6 <+6>:     movl   $0xa,-0xc(%ebp)
   0x004016bd <+13>:    mov    -0xc(%ebp),%eax
   0x004016c0 <+16>:    mov    %eax,0x4(%esp)
   0x004016c4 <+20>:    movl   $0x405064,(%esp)
   0x004016cb <+27>:    call   0x403678 <printf>
   0x004016d0 <+32>:    mov    $0x1,%eax
   0x004016d5 <+37>:    leave
   0x004016d6 <+38>:    ret
End of assembler dump.
(gdb)

ここfuncでは、関数の正確な最初の命令 を指していpush %ebpますが、ブレーク ポイントを設定すると、gdb はスタック フレームの初期化命令の後にブレーク ポイントを設定します。

   0x004016b0 <+0>:     push   %ebp
   0x004016b1 <+1>:     mov    %esp,%ebp
   0x004016b3 <+3>:     sub    $0x28,%esp

関数の命令が実際に始まる場所:

=> 0x004016b6 <+6>:     movl   $0xa,-0xc(%ebp)
   0x004016bd <+13>:    mov    -0xc(%ebp),%eax
   0x004016c0 <+16>:    mov    %eax,0x4(%esp)
   0x004016c4 <+20>:    movl   $0x405064,(%esp)
   0x004016cb <+27>:    call   0x403678 <printf>
   0x004016d0 <+32>:    mov    $0x1,%eax
   0x004016d5 <+37>:    leave
   0x004016d6 <+38>:    ret

ここでこの命令:

movl   $0xa,-0xc(%ebp) ; 0xa = 10

この部分ですか:

int a = 10;
于 2013-10-23T16:20:37.267 に答える
3

gdb は、関数 prologueの後にブレークポイントを設定します。物事が適切に設定される前に、ローカル変数などの期待される状態を表示できなかったためです。

Break for for for ブレークポイントを設定し、プロローグ後の最初の命令のアドレスを出力しますが、print は関数内の実際の最初の命令のアドレスを出力します。

break *0x8048344 を実行して実際の最初の命令にブレークポイントを設定し、そことプロローグの後にローカル変数の値を観察できます。

于 2013-10-23T16:13:28.710 に答える