1

ARM cortex_A9_MPCORE プロセッサを搭載した開発ボード (スノーボール) を使用しており、3.0.8 以降のカーネルで Linux を実行しています。デバッグには GDB と openocd を使用します。

ユーザー モード プロセス、特にテキスト セグメントとユーザー モード スタックのアドレス空間を見つける方法を探しています。

最初に /proc/"PID"/maps を調べました。たとえば、実行中のプロセスの 1 つについて次の出力が得られます。

# cat /proc/1124/maps
00008000-000d5000 r-xp 00000000 b3:02 181        /system/bin/lbsd
000d5000-000f8000 rw-p 000cd000 b3:02 181        /system/bin/lbsd
000f8000-0014a000 rw-p 00000000 00:00 0          [heap]
0014a000-0014c000 rw-p 00000000 00:00 0          [heap]
.
.
.
b0001000-b0009000 r-xp 00001000 b3:02 183        /system/bin/linker
b0009000-b000a000 rw-p 00009000 b3:02 183        /system/bin/linker
b000a000-b0015000 rw-p 00000000 00:00 0 
bea00000-bea21000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

次に、GDB を使用して、init_task から始まるボード上で実行されているタスクのリストを解析するスクリプトを作成しました。タスクごとに、task_struct で見つかった mm_struct の値を取得し、start_code、end_code、および start_stack の値を抽出します。最後に、スクリプトは、mmap が指すさまざまなメモリ領域を解析します。ボードがデバッグ状態にある間にスクリプトが実行され、cortex a9 の両方のコアが停止します。

上記と同じプロセスの GDB スクリプトの出力を次に示します。

taskaddr 0xdf29f140
Name: lbsd
mm start text 8000
mm end text d4ba4
mm start stack bee63df0
####MEMORY REGIONS#####
vm_start 0x8000
vm_end 0xd5000
vm_flags 0x8001875
-----------------------
vm_start 0xd5000
vm_end 0xf8000
vm_flags 0x8101873
-----------------------
vm_start 0xf8000
vm_end 0x14a000
vm_flags 0x100073
-----------------------
vm_start 0x14a000
vm_end 0x14c000
vm_flags 0x100073
-----------------------
.
.
.
-----------------------
vm_start 0xb0001000
vm_end 0xb0009000
vm_flags 0x8000875
-----------------------
vm_start 0xb0009000
vm_end 0xb000a000
vm_flags 0x8100873
-----------------------
vm_start 0xb000a000
vm_end 0xb0015000
vm_flags 0x100073
-----------------------
vm_start 0xbee42000
vm_end 0xbee64000
vm_flags 0x100173
-----------------------
vm_start 0xffff0000
vm_end 0xffff1000
vm_flags 0x40c0055
-----------------------

メモリ領域は、スタックを除いて使用される両方のメソッドで一致します。/proc メソッドの出力では、bea00000 から始まりますが、mm_struct の start_stack フィールドでは、bee63df0 にあり、vm_struct が指すメモリ領域は bee42000 を示します。誰かがこれらの値の違いを説明できますか?

2 番目の質問は、プロセスのテキスト セクションに対応する 00008000 と 000d5000 の間の最初のメモリ領域の値についてです。多くのプロセスがこれらのアドレスを共有していることに気付きました。カーネルはどのようにしてテキスト メモリ領域の実際のアドレスを取得するのでしょうか?

4

1 に答える 1

1

ARM では、スタックが成長します。これは、スタックがより高いアドレスから始まることを意味します。これは、ビットが設定されてvm_flagsいるスタックの に表示されます。vmaVM_GROWSDOWN

スタックvmaにはvm_endof があり、これはof0xbee64000よりも正確に 528 バイト高くなっています。これは、同じ VMA のスタックの一番上に、コマンド ライン、環境、補助ベクトルなどの要素がいくつかあるために発生します。start_stack0xbee63df0

スタック (およびそれだけ) が の別のアドレスにある理由がわかりません/proc/<pid>/maps。カーネル ソース コードを見ると、がその中にある場合にのみvma表示できることがわかります。私が考えることができる唯一の説明は、実行可能ファイルの別の実行からのものであり、スタック以外のすべてに対してアドレスレイアウトのランダム化が無効になっているということです。[stack]start_stackstart_stack/proc/<pid>/mapsvma[stack]


次に、2 番目の質問です。

プロセスの実行中、ハードウェアはページ テーブルを使用して、仮想アドレス (たとえば0x8000) からページの物理アドレスにマップします。カーネルも同じことができます。プロセスのルート ページ テーブル ( pgd)へのポインタが含まれていmm_structます。物理ページ番号 ( pfn) を取得すると、対応する にアクセスできますstruct page。これらすべての操作を行うためのマクロと関数の大規模なセットがあります。

しかし、ページが欠落している可能性があります。たとえば、実行可能ファイルのページの 1 つにまだ障害が発生していない可能性があります。ページ テーブル内のそのページのエントリは、欠落していると表示されます。次に、カーネルは対応する を調べます。このvmaオフセットにはvma、どこかからページを取得するのに十分な情報が含まれており、ページ テーブル内に挿入されます。

于 2012-09-16T17:01:05.177 に答える