知りたい事
c言語で作成 -> gcc でコンパイル&ビルドしたプログラムを gdb でデバッグしています。
gdb を python で制御する機能(※1)をつかって、
オブジェクトのアドレス値をしたいです。
しかし、アドレスを保持している gdb.Value型 のオブジェクトから、
アドレス値を Python の int 型で取得する方法がわからず、
教えてほしいです。
やってみたこと
例えば、以下の c言語プログラム
c
1volatile int gint_val0 = (-1); 2 3int main(int argc, char *args[]){ 4 return 1; 5}
これを、 以下のように、
gcc でコンパイル & ビルド -> gdb に食わせてから、
gdb 内の python を起動して、 gint_val0
のアドレスを取得します。
gdb
1PS C:\Users**\Desktop\github\gdb-py> gcc example.c -o example.exe -g -O0 2PS C:\Users***\Desktop\github\gdb-py> gdb example.exe 3GNU gdb (GDB) (Cygwin 8.1.1-1) 8.1.1 4Copyright (C) 2018 Free Software Foundation, Inc. 5License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 6This is free software: you are free to change and redistribute it. 7There is NO WARRANTY, to the extent permitted by law. Type "show copying" 8and "show warranty" for details. 9This GDB was configured as "x86_64-pc-cygwin". 10Type "show configuration" for configuration details. 11For bug reporting instructions, please see: 12<http://www.gnu.org/software/gdb/bugs/>. 13Find the GDB manual and other documentation resources online at: 14<http://www.gnu.org/software/gdb/documentation/>. 15For help, type "help". 16Type "apropos word" to search for commands related to "word"... 17Reading symbols from example.exe...done. 18(gdb) break main 19Breakpoint 1 at 0x100401094: file example.c, line 4. 20(gdb) run 21Starting program: /cygdrive/c/Users/***/Desktop/github/gdb-py/example.exe 22[New Thread 15508.0x3530] 23[New Thread 15508.0x4558] 24[New Thread 15508.0x27d4] 25[New Thread 15508.0x33f4] 26 27Thread 1 "example" hit Breakpoint 1, main (argc=1, args=0xffffcc20) at example.c:4 284 return 1; 29(gdb) pi # `gdb` 内の Python インタラクティブシェルを起動 30>>> gdbval_gint_val0 = gdb.lookup_symbol("gint_val0")[0].value() # ( 1) `gint_val0` を `gdb.Vlue` 型で取得 31>>> print(int(gdbval_gint_val0)) # ( 2) `gdb.Vlue` -> `int` 型に cast してから `print()`してみる 32-1 # -> `gint_val0` に代入した `-1` が Python の int に cast できている 33>>> gdbval_gint_val0_adr = gdbval_gint_val0.address # ( 3) `gint_val0` のアドレス を `gdb.Value` 型として取得 34>>> print(int(gdbval_gint_val0_adr)) # ( 4) アドレスを `gdb.Vlue` -> `int` 型に cast してから `print()`してみる 35Traceback (most recent call last): # -> アドレス値 -> `int` 型に cast された値が print されることを期待したけど、 36 File "<stdin>", line 1, in <module> # Exception になってしまう 37gdb.error: Cannot convert value to int. 38>>> print(gdbval_gint_val0_adr) # ( 5) cast せずに `print()` してみる 390x100402010 <gint_val0> # -> アドレス値を表示できたけど `<変数名>` が付加されてしまう 40>>> print(str(gdbval_gint_val0_adr)) # ( 6) `string` に cast してから `print()` してみる 410x100402010 <gint_val0> # -> cast しないで `print()` した場合と同じ結果。 42>>>
上記中、 (3)
の手順で gdb.Value
の .address
から得られるオブジェクトは、
※2 にあるように、gdb.Value
型なので、 Python の int 型に cast できると思ったのですが、
結果の (4)
で Exception になってしまいます。
試しに、 (5)
と (6)
のように、 直接 print()
したり Python の string 型に cast すれば、
Exception は発生せずに string 型として取得できるのは分かりましたが、
以下の問題があります。
- (1of2)
表示されているように、 <変数名>
が付加されてしまいます。
取得した string 値を文字列操作すれば不要な部分は 取り除けるとは思いますが、
上記の様に print()
できているということは、 gdb.Value
は 0x???? の値がいくつなのかはわかっているはずです。
Python の string 型に cast した後に、 わざわざ文字列操作してやっと 0x???
を取得するのは、スマートではないと思うんです。
- (2of2)
取得できる型は string 型です。
メモリアドレスは数値型なので、 int 型で取得したい場合は、
(1of2)
の問題を、文字列操作で 0x???
の形になるように操作してから、
さらに 16進数文字列 -> int 型変換が必要です。
(大して難しい事ではないと思いますが、やらなくて済む方法があるならその方法を使いたいです)
オブジェクトのアドレスを保持している gdb.Value
からアドレス値 だけ を取得する方法はあるのでしょうか?
使用環境
使用している環境は以下のとおりです
OS -> Windows10
gcc ver -> 7.4.0
gdb ver -> 8.1.1
python ver -> 3.7.2
出典
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。