使用GDB打印IP地址

4
我正在调试一个网络代码,并想要打印已声明为int32的IP地址。当使用gdb print命令打印时,我得到了一些不太有意义的值。
如何以有意义的格式打印它们?
7个回答

10

只需使用inet_ntoa(3)即可:

(gdb) p (char*)inet_ntoa(0x01234567)  # Replace with your IP address
$1 = 0xa000b660 "103.69.35.1"

IPv6地址是否也有类似的可能性? - Prof. Moriarty
我怀疑过,甚至在询问之前尝试过,但第三个参数该给什么?我尝试了不同的方法,但一直收到SIGSEGV错误。 - Prof. Moriarty
你需要传递一个低级进程地址空间中的地址。你可以在某个未使用的全局缓冲区中获取一些内容,或者你可以自己使用malloc函数分配内存,例如:(gdb) p (void*)malloc(64); $1 = (void *) 0x12345678; (gdb) p (char*)inet_ntop(23,&my_ip6_addr,0x12345678,64) - Adam Rosenfield

7
如果您正在调试核心文件并且无法使用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)
以上是一段代码,它将整数转换为IP地址格式。通过使用位运算和printf语句,您可以将整数分解为其四个字节,并在每两个字节之间插入一个点号来创建IP地址。

4

然而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“用户定义函数”:

(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数据元素的结构体的有效指针)。但似乎gdb用户定义的函数不允许使用sprintf()调用。

-丹尼斯·贝德纳尔,2012年12月


请注意,在小端系统(如x86)上,此答案将以反向打印您的IP地址。网络字节顺序地址(例如通常提供给inet_ntoa的地址)将在这些体系结构上以最不重要的字节中的第一个八位组存储。 - Dave Goodell

2
解释Gopinath的回应:
(gdb) p/uc (char[4]) 342757386
$4 = {10 '\n', 16 '\020', 110 'n', 20 '\024'}

p/uc: 告诉gdb将数据视为无符号字符内容。

(char[4]) 342757386: 将IP转换为由4个char元素组成的数组,每个元素表示一个字节/八位字节。

因此,您告诉gdb将IP的十进制表示视为四个字节的数组 - 四个八位字节 - 然后将它们打印为无符号字符。

如果您忽略每个字节的ASCII表示,则可以得到您的IP地址:10.16.110.20


1
创建一个调用inet_ntoa函数的函数,然后在gdb中使用“p”命令调用该函数并传入你的int参数。

0

尝试使用此命令:

(gdb) p/uc (char[4])342757386
$1 = {10 '\n', 16 '\020', 110 'n', 20 '\024'}

0

这里有另一种有趣的方法:

#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";
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接