Bug #9654
Segmentation fault while printing out C level backtrace information
Description
When SIGSEGV happens, C level backtrace information should be printed out, but the printing-out itself causes another segmentation fault.
$ ./ruby -e 'Process.kill :SEGV, $$' -e:1: [BUG] Segmentation fault at 0x00584f ruby 2.2.0dev (2014-03-19) [powerpc64-linux] -- Control frame information ----------------------------------------------- c:0003 p:---- s:0009 e:000008 CFUNC :kill c:0002 p:0015 s:0004 E:00153c EVAL -e:1 [FINISH] c:0001 p:0000 s:0002 E:002574 TOP [FINISH] -- Ruby level backtrace information ---------------------------------------- -e:1:in `<main>' -e:1:in `kill' -- C level backtrace information ------------------------------------------- ./ruby(Segmentation fault
This second segmentation fault happens at the following stack context.
(gdb) bt #0 0x201ba994 in strlen () from /lib/libc.so.6 #1 0x2070cbe0 in kvprintf (fmt=0x207a097d "+0x%lx) [0x%lx] %s:%d\n") at addr2line.c:1009 #2 kprintf (fmt=0x207a097d "+0x%lx) [0x%lx] %s:%d\n") at addr2line.c:771 #3 0x2070e4f8 in rb_dump_backtrace_with_lines (num_traces=18, traces=0x2081762c, syms=0x20a7d720) at addr2line.c:677 #4 0x206f3ffc in rb_print_backtrace () at vm_dump.c:690 #5 rb_vm_bugreport () at vm_dump.c:825 #6 0x207621ac in report_bug (file=<value optimized out>, line=<value optimized out>, fmt=0x2079857c "Segmentation fault at %p", args=0x2085f864) at error.c:312 #7 0x207624e4 in rb_bug (fmt=0x2079857c "Segmentation fault at %p") at error.c:339 #8 0x206664e0 in sigsegv (sig=<value optimized out>, info=0x2085f8f0, ctx=<value optimized out>) at signal.c:704 #9 <signal handler called> #10 0x2016674c in kill () from /lib/libc.so.6 #11 0x20702c64 in ruby_kill (pid=<value optimized out>, sig=<value optimized out>) at thread.c:5185 <<<<< snip >>>>>
This error began to occur after this change:
http://www.rubyist.net/~kanemoto/chkbuild/plinux/ruby-trunk/log/20140314T070002Z.diff.html.gz
Due to this error, TestBugReporter#test_bug_reporter_add
fails on ppc64 GNU/Linux.
My guess is that the changes in addr2line.c are doing something, but I am not sure.
The second segmentation fault is caused because line->sname
points to out-of-range memory.
Tracing rb_dump_backtrace_with_lines()
and fill_lines()
, I found the sname
entry was first set correctly by reading the ./ruby
file, but it was later overwritten by some incorrect information while reading the /usr/lib/debug/lib/libc-2.5.so.debug
file.
In libc-2.5.so.debug
, there seem to be several symbol table entries whose st_size
is quite big (~1.5 GB), so those entries happen to cover all the addresses in traces[]
, which results in overwritting sname
at the line 584 of addr2line.c.
I am not familiar with ELF, so I cannot track down further.
Hope this report helps.
Associated revisions
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (fill_lines): compare the file names of object in which symbols exist. [Bug #9654] [ruby-dev:48058]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45391 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
- addr2line.c (parse_debug_line_cu): explicitly specify signed char because DWARF's line_Base is signed char and char maybe unsigned. patched by Rei Odaira. [ruby-dev:48068] [Bug #9654]
History
Updated by nobu (Nobuyoshi Nakada) almost 5 years ago
- Description updated (diff)
- Category set to core
- Status changed from Open to Assigned
- Assignee set to naruse (Yui NARUSE)
- Target version set to 2.2.0
- Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN to 2.0.0: DONTNEED, 2.1: DONTNEED
Updated by naruse (Yui NARUSE) almost 5 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
Updated by ReiOdaira (Rei Odaira) almost 5 years ago
Thanks for the quick fix. The second segmentation fault no longer happens.
Unfortunately, I found another problem regarding the C-level backtrace. Here is what I see in my environment (ruby 2.2.0dev (2014-03-23) [powerpc64-linux]):
$ ./ruby -e 'Process.kill :SEGV, $$' -e:1: [BUG] Segmentation fault at 0x004731 ruby 2.2.0dev (2014-03-23) [powerpc64-linux] -- Control frame information ----------------------------------------------- c:0003 p:---- s:0009 e:000008 CFUNC :kill c:0002 p:0015 s:0004 E:001b24 EVAL -e:1 [FINISH] c:0001 p:0000 s:0002 E:002384 TOP [FINISH] -- Ruby level backtrace information ---------------------------------------- -e:1:in `<main>' -e:1:in `kill' -- C level backtrace information ------------------------------------------- ./ruby(rb_vm_bugreport+0x134) [0x20294264] vm_dump.c:58285 ./ruby(report_bug+0x1ac) [0x2030250c] error.c:242232 ./ruby(rb_bug+0xc4) [0x20302844] error.c:255315 ./ruby(sigsegv+0xb0) [0x202064f0] signal.c:15040 (__kernel_sigtramp_rt32+0x0) [0x100360] ./ruby(ruby_kill+0x118) [0x202a2ee8] thread.c:495680 ./ruby(rb_f_kill+0x98) [0x202074f8] signal.c:97721 ./ruby(call_cfunc_m1+0x2c) [0x2027294c] vm_insnhelper.c:10546 ./ruby(vm_call_cfunc_with_frame+0x14c) [0x2027c5ac] vm_insnhelper.c:768981 ./ruby(vm_call_method+0x580) [0x20291c60] vm_method.c:2680506 ./ruby(vm_exec_core+0x2288) [0x202899a8] vm.inc:1934715 ./ruby(vm_exec+0x6f8) [0x2028d8c8] vm.c:2278215 ./ruby(rb_iseq_eval_main+0x2f8) [0x2028def8] vm_insnhelper.c:2310457 ./ruby(ruby_exec_internal+0xe4) [0x20131884] eval.c:153339 ./ruby(ruby_run_node+0xa4) [0x201336c4] eval.c:326460 ./ruby(main+0x5c) [0x2012f77c] main.c:1828 <<<<< snip >>>>>
The line numbers are incorrect. In DWARF, line_base
is signed 8 bits, but parse_debug_line_cu()
reads line_base
as char
, which is not guaranteed as signed in the C language. The following patch will fix this.
--- addr2line.c (revision 45390) +++ addr2line.c (working copy) @@ -294,7 +294,7 @@ is_stmt = default_is_stmt = *(unsigned char *)p; p++; - line_base = *(char *)p; + line_base = *(signed char *)p; p++; line_range = *(unsigned char *)p;
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45383 b2dd03c8-39d4-4d8f-98ff-823fe69b080e