gdbを使用したIPアドレスの印刷
-
08-07-2019 - |
質問
ネットワークコードをデバッグしていて、 int32
として宣言されているIPアドレスを出力したい。
gdb printコマンドを使用して印刷すると、あまり意味のない値が得られます。
どうすれば意味のある形式で印刷できますか?
解決
inet_ntoa(3)
を次のように使用します。
(gdb) p (char*)inet_ntoa(0x01234567) # Replace with your IP address
$1 = 0xa000b660 "103.69.35.1"
他のヒント
コアファイルをデバッグしていて、inet_ntoa()を使用できない場合は、次のようなこともできます。
(gdb) set $int_ip = 0x01234567 (gdb) printf "%d.%d.%d.%d\n", ($int_ip & 0xff), ($int_ip >> 8) & 0xff, ($int_ip >> 16) & 0xff, ($int_ip >> 24) 103.69.35.1 (gdb)
しかし、inet_ntoa()はu_int32_t引数ではなく、struct in_addr引数を取るため、前の答えは次のとおりです。 p(char *)inet_ntoa(3) 私には間違っているようです。
gdb.cmd.txtという名前のファイルで関数を定義する方法は次のとおりです。したがって、" gdb -x gdb.cmd.txt"を呼び出します。起動時。
gdb.cmd.txtに次のように入力します:
define ntoa
set $ipv4 = $arg0
echo IPV4 =.
p $ipv4
set $val1 = ($ipv4 >> 24) & 0xff
set $val2 = ($ipv4 >> 16) & 0xff
set $val3 = ($ipv4 >> 8) & 0xff
set $val4 = ($ipv4 >> 0) & 0xff
printf "IPV4=%u=0x%02x.%02x.%02x.%02x =%d.%d.%d.%d\n", $ipv4, $val1, $val2, $val3, $val4, $val1, $val2, $val3, $val4
end
次にgdbを実行し、ntoa" user defined function"を呼び出します。次のとおりです。
(gdb) ntoa(0x01020304)
IPV4 =.$10 = 16909060
IPV4=16909060=0x01.02.03.04 =1.2.3.4
(gdb) ntoa(-1)
IPV4 =.$10 = -1
IPV4=4294967295=0xff.ff.ff.ff =255.255.255.255
ところで:gdbで関数が書式設定された文字列を返す方法があるかどうかを検索しています。コマンド" p ntoa(0x01020304)"を実行できます。または" p ntoa(ptr-> ipv4_addresss)" (ptrがu_int32_t ipv4_address"データ要素を含む構造への有効なptrであると仮定します)。しかし、gdbユーザー定義関数はsprintf()呼び出しを許可しないようです。
-dennis bednar 2012年12月
inet_ntoaを呼び出す関数を作成し、intのgdbで「p」コマンドを使用して呼び出します。
Gopinathの応答の説明:
(gdb) p/uc (char[4]) 342757386
$4 = {10 '\n', 16 '\020', 110 'n', 20 '\024'}
p / uc
:gdbにデータを符号なしcharコンテンツとして扱うように指示します。
(char [4])342757386
:IPを4つのchar要素の配列にキャストします。各要素は1バイト/オクテットを表します。
したがって、gdbにIPの10進表現を4バイトの配列(4オクテット)として扱い、それらを符号なし文字として出力するように指示しています。
各バイトのASCII表現を無視すると、IPアドレスは 10.16.110.20
になります。
別の興味深い方法があります:
#include <sys/types.h> // u_int32_t
// next 3 for inet_ntoa() call
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// C++ headers
#include <iostream> // std::cout
#include <string>
#include <sstream> // ostringstream
// class to aid in using the gdb(3) debugger to print a u_int32_t ip_address as a string.
// The toString() is a static method!!
// How to call a C++ method from the gdb debugger, to simulate the inet_nto(3) method
//
// From within gdb debugger, you must have a process, so first stop at main:
// b main
// r
//
// (gdb) p MYIP4::toString(0x0fffefdfc)
// $1 = "255.254.253.252"
//
// (gdb) p MYIP4::toString(-1)
// $2 = "255.255.255.255"
//
// (gdb) p MYIP4::toString(65536)
// $3 = "0.1.0.0"
//
// Drawbacks: the a.out executable that you are debugging needs the MYIP4 class already
// compiled and linked into the executable that you are debugging.
//
// PS: I don't know if there is a "slick way" where the MyIP4 class could dynamically be loaded,
// within gdb(), if the executable failed to contain the MYIP4 class.
//
// PS: I had trouble with my operator() idea.. If you know how to improve on it, post away!
//
// @author 1201207 dpb created
//=============================
class MYIP4
{
public:
static std::string toString(u_int32_t ipv4_address )
{
struct in_addr temp_addr;
// inet_ntoa() returns a char * to a buffer which may be overwritten
// soon, so convert char* to a string for extra safety.
temp_addr.s_addr = htonl(ipv4_address);
std::string ipv4String = std::string(inet_ntoa( temp_addr ));
return ipv4String;
}
#if 0
// this idea did NOT work, so it is commented out.
//
// overload the () operator, so that, within gdb, we can simply type:
// p MYIP4(0x01020304)
// instead of:
// p MYIP4::toString(0x01020304)
std::string operator() ( u_int32_t ipv4_address )
{
return toString(ipv4_address);
}
#endif
};
void test1();
int main()
{
test1();
return 0;
}
void test1()
{
u_int32_t ipv4Address = 0x01020304; // host byte order for 1.2.3.4
std::cout << "Test1: IPAddress=" << MYIP4::toString(ipv4Address) << "\n";
}
このコマンドを試してください:
(gdb) p/uc (char[4])342757386
$1 = {10 '\n', 16 '\020', 110 'n', 20 '\024'}