如何使用GDB分析通向系统库的堆栈跟踪?

如何使用GDB分析通向系统库的堆栈跟踪?,gdb,segmentation-fault,stack-trace,Gdb,Segmentation Fault,Stack Trace,我试图找出系统库级别上发生segfault的原因。 我想获得一些关于如何使用gdb检查以下堆栈跟踪中看到的getenv()调用的参数的提示 如跟踪所示-getenv()不是由我的代码直接调用的-调用嵌套在我的代码中启动的系统调用链中。调用从我的例程a_logmsg()开始,尝试获取线程安全的localtime-localtime\r(),然后在libc代码中的某个地方调用getenv()。操作系统是Solaris 8/SPARC Program terminated with signal 11


我试图找出系统库级别上发生segfault的原因。 我想获得一些关于如何使用gdb检查以下堆栈跟踪中看到的
getenv()
调用的参数的提示

如跟踪所示-
getenv()
不是由我的代码直接调用的-调用嵌套在我的代码中启动的系统调用链中。调用从我的例程
a_logmsg()
开始,尝试获取线程安全的
localtime-localtime\r()
,然后在libc代码中的某个地方调用
getenv()
。操作系统是Solaris 8/SPARC

Program terminated with signal 11, Segmentation fault.
#0  0xfed3c9a0 in getenv () from /usr/lib/libc.so.1
(gdb) where
#0  0xfed3c9a0 in getenv () from /usr/lib/libc.so.1
#1  0xfed46ab0 in getsystemTZ () from /usr/lib/libc.so.1
#2  0xfed44918 in ltzset_u () from /usr/lib/libc.so.1
#3  0xfed44140 in localtime_r () from /usr/lib/libc.so.1
#4  0x00029c28 in a_logmsg (fmt=0xfd5d0 "%s: no changes to config.") at misc.c:155
#5  0x000273b8 in a_sync_device (device_group=0x11e3ed0 "none", hostname=0xfbbffe8d "router",
    config_by=0xfbbffc8f "scheduled_archiving", platform=0x11e3ee0 "cisco", authset=0x11e3ef0 "set01",
    arch_method=0xffffcfc8 <Address 0xffffcfc8 out of bounds>) at arch.c:256
#6  0x00027ce8 in a_archive_single (arg=0x1606f50) at arch.c:498
#7  0xfe775378 in _lwp_start () from /usr/lib/libthread.so.1
#8  0xfe775378 in _lwp_start () from /usr/lib/libthread.so.1
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
程序以信号11终止,分段故障。
#来自/usr/lib/libc.so.1的getenv()中的0 0xfed3c9a0
(gdb)在哪里
#来自/usr/lib/libc.so.1的getenv()中的0 0xfed3c9a0
#来自/usr/lib/libc.so.1的getsystemTZ()中的1 0xfed46ab0
#来自/usr/lib/libc.so.1的ltzset_()中的2 0xfed44918
#3/usr/lib/libc.so.1中的localtime_r()中的0xfed44140
#4 0x00029c28在杂项c:155处的日志消息(fmt=0xfd5d0“%s:配置无更改”)中
#5 0x000273b8在同步设备中(设备组=0x11e3ed0“无”,主机名=0xfbbffe8d“路由器”,
config_by=0xfbbffc8f“定时存档”,platform=0x11e3ee0“cisco”,authset=0x11e3ef0“set01”,
拱门c:256处的拱门法=0xffffcfc8)
#6 0x00027ce8在拱门处的单个存档(arg=0x1606f50)中。c:498
#7 0xfe775378,位于/usr/lib/libthread.so.1的_lwp_start()中
#8 0xfe775378位于/usr/lib/libthread.so.1的_lwp_start()中
反向跟踪停止:上一帧与此帧相同(堆栈损坏?)
我想获得一些关于如何使用gdb检查以下堆栈跟踪中看到的getenv()调用的参数的提示

  • Solaris libc的源代码可用
  • 通过设置断点并查看寄存器,可以检查
    getenv
    的参数。您需要知道所使用的参数,但它非常简单--
    getenv
    的参数在寄存器
    i0
    中,并且
    print(char*)$i0
    (gdb)
    提示符下应该打印
    “TZ”
  • 最后,在
    getenv
    中发生崩溃的最可能原因是您先前破坏了环境。特别要注意的是,此代码是错误的:


    很可能,您会在那里看到不包含
    =
    符号的字符串。

    请注意,
    getsystemTZ()
    只是调用
    getenv(“TZ”)
    (以及之后的其他内容),这很可能是其自身分段错误的原因。由于内存损坏的问题,真正的罪魁祸首通常是在其他地方,在代码中,在您观察到崩溃的地方之前执行。您应该先检查自己的代码。在本例中,
    a.*
    -至少起作用。您好,感谢您对
    getsystemTZ()
    的评论。正如我在下文中所述,segfault的直接原因似乎是
    environ
    变量的损坏,
    getenv()
    正试图访问该变量,它确实看起来像是由我的代码引起的内存问题。感谢分享您的见解。i0寄存器确实包含“TZ”,它无疑是
    getenv()调用的参数
    x/100s environ
    返回“地址超出边界”,因此看起来
    environ
    变量以某种方式损坏,而
    getenv()
    只是试图访问不存在的地址,从而导致segfault。事实上,这看起来像是我的代码导致的内存损坏——我将不得不更仔细地研究它。
    void buggy()
    {
       char buf[80];
       strcpy(buf, "FOO=BAR");
       putenv(buf);  // <-- BUG!
    }
    
    (gdb) x/100s __environ
    (gdb) x/100s environ