LINUX 段错误查找记录 -- segfault at fffffffffffffff9 ip 0000003c97e7b81c sp 00007fffad7c0638 error 4 in lib

119.*.*.45 app 总是段错误, 且不产生core文件(ulimit -c unlimited 设置)

grep segfault /var/log/messages
Oct 31 17:39:40 -45 kernel: *Serve[9909]: segfault at 3946 ip 0000000000003946 sp 00007f8de69a9e18 error 14 in *Server[400000+13000]
Oct 31 18:32:41 r-45 kernel: *Serve[17038]: segfault at 7de6 ip 0000000000007de6 sp 00007f09cacf9128 error 14 in *Server[400000+13000]
Oct 31 18:53:43 r-45 kernel: *Serve[17281]: segfault at 13a4 ip 0000003c0ac0920b sp 00007f1ebdd64bc0 error 4 in ld-2.12.so[3c0ac00000+20000]

dmesg | tail -30
*Info[5879]: segfault at 7d1 ip 0000003c0b0480ac sp 00007fff0ef9d540 error 4 in libc-2.12.so[3c0b000000+18a000]
*Serve[17038]: segfault at 7de6 ip 0000000000007de6 sp 00007f09cacf9128 error 14 in *Server[400000+13000]
*Serve[17281]: segfault at 13a4 ip 0000003c0ac0920b sp 00007f1ebdd64bc0 error 4 in ld-2.12.so[3c0ac00000+20000]

glibc 库版本查看
ldd 
(GNU libc) 2.12  对malloc 是非线程安全版本  至少需要>= 2.3.6

以“*Serve[17038]: segfault at 7de6 ip 0000000000007de6 sp 00007f09cacf9128 error 14 in *Server[400000+13000]”为例
IP is the Instruction Pointer aka Program Counter. SP is the stack pointer. 
The 'error 4' is a low-level error code which is irrelevant for us.


objdump -D | grep 7de6
 407de6:       bb ff ff ff ff          mov    $0xffffffff,%ebx
 17de6:       01 03                   add    %eax,(%rbx)

 400000 - 7de6(ip) = 3F821A

 whith gdb:
 info symbol *3F821A

 errcode 详见linux 内核源码arch/*/mm/fault.c 描述, 
  * Page fault error code bits:
 *
 *   bit 0 == 0: no page found1: protection fault
 *   bit 1 == 0: read access1: write access
 *   bit 2 == 0: kernel-mode access1: user-mode access
 *   bit 3 == 1: use of reserved bit detected
 *   bit 4 == 1: fault was an instruction fetch


address - the location in memory the code is trying to access (it's likely that 10 and 11 are offsets from a pointer we expect to be set to a valid value but which is instead pointing to 0)
ip - instruction pointer, ie. where the code which is trying to do this lives
sp - stack pointer
error - Architecture-specific flags; see arch/*/mm/fault.c for your platform.

Event for a shared lib, the "[3c0ac00000+20000]" part should give a hint where the crashing segment of the lib was mapped in memory. "readelf --segments mylib.so" lists these segments, and then you can calculate the EIP offset into the crashing segment and feed that to addr2line (or view it in "objdump -dgS").


backtrace、backtrace_symbols、backtrace_symbols_fd 可以打印函数调用的堆栈
通过捕捉SIGSEGV信号, 在信号处理函数中调用堆栈函数, 打印函数down挡掉时的堆栈
具体见man 手册


gcc 自带内置的函数可以打印堆栈地址:
__builtin_return_address() 返回一个地址(指针形式)


eg:// get current address
void* p = __builtin_return_address(0);
printf("0x%x\n", p);
// get callee address
p = __builtin_return_address(1); 
// we cannot get more addresses as we don't have any
// information about how many leves of calls we have

libunwind库可以打印详细的堆栈调用, 需下载安装, 再查看man手册使用

sigaction函数sa_sigaction => siginfo_t => si_addr引起错误的内存地址


段错误:
Nov  3 17:03:54 haier-45 kernel: haierUpassServe[22708]: segfault at 3946 ip 0000000000003946 sp 00007f56edf20e18 error 14 in haierUpassServer[400000+13000]
以上信息说明:
开始是系统当前时间
进程名字及pid
segfault at 引起故障的地址
ip 指令的内存地址
sp 堆栈指针地址, 及栈顶指针
err is not an errno nor a signal numbe, but page fault error code
[400000+13000] 对象崩溃时映射的虚拟内存起始地址和大小


addr2line -e app ip


demon[3702]:segfault at b771c488 ip b771c4b3 sp bfc8b1a0 error 7 in libmodule.so[b771c000+1000]
上面的b771c000是libmodule.so的载入地址,所以运行
addr2line -e libmodule.so ip地址-模块载入地址(b771c4b3-b771c000)
此处也可根据程序ip指令地址 - 模块载入地址, 然后反汇编相应的动态库, 在反汇编中查找相应的差值(.so文件中指令地址为相对地址, 满足共享需要)
如果指令为程序中, 可直接反汇编程序, 在反汇编中查找相应指令地址 


或者gdb重新运行程序,break在相应的指令地址




如果关注的backtrace位于一个动态链接库中,那么麻烦一些,因为动态链接库的基地址不是固定的。
程序每次运行加载动态库的地址是不一样的
这个时候,首先要把进程的memory map找来。在Linux下,进程的memory map可以在/proc/<pid>/maps文件中得到。然后在这个文件中找到动态链接库的基地址,然后将backtrace中的地址 – 动态链接库的基地址,得到偏移地址offset address, 最后addr2line -C -f -e <shared library> <offset address>。(此方法,进程一结束
proc目下下相应的pid就不存在了) 调用pmap命令也可 、 /proc/pid/maps


dladdr可在程序运行时得到本程序加载的动态库信息
dl_iterate_phdr功能同上, 但感觉更好用些, 具体见man手册


objdump -DCl ./app 反汇编:
08048544 <main>:
main():
/mnt/hgfs/D/code/vm_proj_saving/myproj/c/segfault.c:6
 8048544: 55                   push   %ebp
 8048545: 89 e5                mov    %esp,%ebp
 8048547: 83 e4 f0             and    $0xfffffff0,%esp
 804854a: 83 ec 20             sub    $0x20,%esp
/mnt/hgfs/D/code/vm_proj_saving/myproj/c/segfault.c:7
 804854d: c7 44 24 1c 00 00 00 movl   $0x0,0x1c(%esp)
 8048554: 00 
/mnt/hgfs/D/code/vm_proj_saving/myproj/c/segfault.c:9
 8048555: b8 44 86 04 08       mov    $0x8048644,%eax
注意没有加$的数表示内存地址, 而不表示立即数(立即数即为数字, 而非变量)

.o 文件所有指令中用到的符号地址都是相对地址, 下一步链接器要修改这些指令,把其中的地址都改成 加载时的内存地址,这些指令才能正确执行。


总结:可以在程序中打印动态库加载地址(dl_iterate_phdr, dladdr)信息, 打印动态库加载地址信息主要是为了算crash发生在动态库中的具体编译地址, 至于段错误信号, 可以通过信号捕捉, 在信号处理函数中打印进程crash时堆栈, 打印堆栈有上边三个函数(__builtin_return_address()、backtrace()、libunwind库需安装,再man libunwind查看使用方法)均可打印, 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
引用中的链接提到的错误信息"segfault at 0 ip (null) sp 00007f329e870418 error 14 in main[400000 23c000]"是指发生了一个段错误(segmentation fault)。段错误通常是由于程序访问了不存在的内存地址或者非法的内存访问引起的。具体来说,"segfault at 0"表示在地址0处发生了段错误。这个错误信息中提到的ipsp分别表示指令指针和栈指针的值。而"error 14"则是表示发生了一个无效的页错误。根据这个错误信息,我们可以推断出在程序的main函数中发生了段错误。不过,需要注意的是,这个错误信息中的指令指针(ip)为(null),这可能意味着没有正确的调试符号(debug symbol)来解析函数名。所以,我们需要进一步分析系统日志或者其他相关信息来确定具体的原因和解决方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python出现segfault错误解决方法](https://download.csdn.net/download/weixin_38616330/12875269)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [没有core文件时定位segfault at 0 ip (null) 的问题(三):艰难定位,多种原因](https://blog.csdn.net/lianshaohua/article/details/107933181)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Coredump-N, segfault at 0 ip 0000000000000000 sp; 被kernel 抓到](https://blog.csdn.net/qq_36428903/article/details/122855636)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值