Cannot parse DWARF sections properly

Following code produces OverflowError under my developing Linux distribution.

begin
  pp caller
rescue e : Exception
  p e.class
end

I could not reproduce this error on openSUSE Tumbleweed (with the same version of LLVM, with BFD ld), and I think other major released Linux distributions also does not produce this problem.

Can you investigate the problem with me?

To summarize below details, in my developing Linux distribution:

  • Crystal cannot parse DWARF sections of binaries built by our BFD ld.
    • Exposed problem is OverflowError, but it may not be all.
    • In other major Linux distributions, this problem seem not to be raised.
  • GDB can normally parse them.
  • The binaries built by GOLD ld seem to be parsed normally.

[momonga@elma ~/crystal x86_64]$ cat test.cr
begin
  pp caller
rescue e : Exception
  p e.class
end
[momonga@elma ~/crystal x86_64]$ bin/crystal build test.cr
Using compiled compiler at `.build/crystal'
/usr/bin/ld: skipping incompatible /usr/lib/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/libpthread.so when searching for -lpthread
/usr/bin/ld: skipping incompatible /usr/lib/librt.so when searching for -lrt
/usr/bin/ld: skipping incompatible /usr/lib/libdl.so when searching for -ldl
/usr/bin/ld: skipping incompatible /usr/lib/libc.so when searching for -lc
[momonga@elma ~/crystal x86_64]$ ./test
OverflowError

GDB gives the informative backtrace, so reading process of DWARF sections used in GDB seems OK.

[momonga@elma ~/crystal x86_64]$ gdb ./test
GNU gdb (GDB) 8.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-momonga-linux".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) b __crystal_raise
Breakpoint 1 at 0x441840: file /opt/momonga/crystal/src/raise.cr, line 191.
(gdb) r
Starting program: /opt/momonga/crystal/test
[New LWP 26966]
[New LWP 26967]
[New LWP 26968]

Thread 1 "test" hit Breakpoint 1, __crystal_raise ()
    at /opt/momonga/crystal/src/raise.cr:191
191     {% unless flag?(:win32) %}
(gdb) bt
#0  __crystal_raise () at /opt/momonga/crystal/src/raise.cr:191
#1  0x000000000044efee in raise () at /opt/momonga/crystal/src/raise.cr:191
#2  0x00000000004418ce in __crystal_raise_overflow ()
    at /opt/momonga/crystal/src/raise.cr:239
#3  0x000000000048d5aa in read_opcodes ()
    at /opt/momonga/crystal/src/debug/dwarf/line_numbers.cr:240
#4  0x000000000048cd76 in decode_sequences ()
    at /opt/momonga/crystal/src/debug/dwarf/line_numbers.cr:229
#5  0x000000000048c34c in initialize ()
    at /opt/momonga/crystal/src/debug/dwarf/line_numbers.cr:176
#6  0x000000000048c2a4 in new ()
    at /opt/momonga/crystal/src/debug/dwarf/line_numbers.cr:173
#7  0x00000000004566e8 in read_dwarf_sections ()
    at /opt/momonga/crystal/src/callstack.cr:218
#8  0x0000000000453e1d in decode_line_number ()
    at /opt/momonga/crystal/src/callstack.cr:218
#9  0x00000000004535a8 in decode_backtrace ()
    at /opt/momonga/crystal/src/callstack.cr:163
#10 0x0000000000453462 in printable_backtrace ()
    at /opt/momonga/crystal/src/callstack.cr:52
#11 0x000000000044c5dd in caller () at /opt/momonga/crystal/src/callstack.cr:23
#12 0x0000000000440c26 in __crystal_main ()
    at /opt/momonga/crystal/src/time/location/loader.cr:2
#13 0x00000000004bd879 in main_user_code ()
    at /opt/momonga/crystal/src/crystal/main.cr:97
#14 0x00000000004bd7d9 in main ()
    at /opt/momonga/crystal/src/crystal/main.cr:86
#15 0x000000000044c2a6 in main ()
    at /opt/momonga/crystal/src/crystal/main.cr:106
(gdb) quit
A debugging session is active. 
Inferior 1 [process 26962] will be killed.


Quit anyway? (y or n) y

Also, using GOLD ld is OK.

[momonga@elma ~/crystal x86_64]$ CC="gcc -fuse-ld=gold" bin/crystal build -o test.gold test.cr
Using compiled compiler at `.build/crystal'
/usr/bin/ld.gold: warning: skipping incompatible /usr/lib/libm.so while searching for m
/usr/bin/ld.gold: warning: skipping incompatible /usr/lib/libpthread.so while searching for pthread
/usr/bin/ld.gold: warning: skipping incompatible /usr/lib/librt.so while searching for rt
/usr/bin/ld.gold: warning: skipping incompatible /usr/lib/libdl.so while searching for dl
/usr/bin/ld.gold: warning: skipping incompatible /usr/lib/libc.so while searching for c
[momonga@elma ~/crystal x86_64]$ ./test.gold
["test.cr:2:6 in '__crystal_main'",
 "src/crystal/main.cr:97:5 in 'main_user_code'",
 "src/crystal/main.cr:86:7 in 'main'",
 "src/crystal/main.cr:106:3 in 'main'",
 "__libc_start_main",
 "_start",
 "???"]

Dumping DWARF data with objdump -g does not cause error.

Crystal version is:

[momonga@elma ~/crystal x86_64]$ bin/crystal -v
Using compiled compiler at `.build/crystal'
Crystal 0.32.0-dev [10d92bbac] (2019-10-18)

LLVM: 8.0.1
Default target: x86_64-unknown-linux-gnu

Hi, and welcome to the Crystal forums!

It seems this is a bug. It would be best to report it here: https://github.com/crystal-lang/crystal/issues

It seems the problem is this line:

opcode_base has a type of UInt8, and if that happens to be 0 then 0_u8 - 1 will underflow. Putting that 1.upto inside if sequence.opcode_base > 0 would make it work.

To see if this indeed fixes you problem, you can add these line to the top of your program:

module Debug
  module DWARF
    struct LineNumbers
      private def read_opcodes(sequence)
        return unless sequence.opcode_base > 0

        1.upto(sequence.opcode_base - 1) do
          sequence.standard_opcode_lengths << @io.read_byte.not_nil!
        end
      end
    end
  end
end

Let me know!

Unrelated, but I wonder if the “OverflowError” error message could somehow be made more informative…
Like “Integer overflowError” or the like.
As it is I was confused and assumed it was a stack overflow… :)
Or is that an underflow? I’m not sure… :)

1 Like

Thank you for your replies!

I opened an issue with the result of provided fix here: https://github.com/crystal-lang/crystal/issues/8352


The message OverflowError is not the actual message, but the class of Exception. The actual message will be “Arithmetic overflow”. Sorry for the confusion.

Technically, they seem not to say “underflow” for operations that the result value becomes smaller than the smallest representable value: https://en.wikipedia.org/wiki/Integer_overflow#Definition_variations_and_ambiguity

1 Like