diff --git a/src/crystal/dwarf/abbrev.cr b/src/crystal/dwarf/abbrev.cr index bf29d8d56744..46190a4e0323 100644 --- a/src/crystal/dwarf/abbrev.cr +++ b/src/crystal/dwarf/abbrev.cr @@ -237,10 +237,9 @@ module Crystal @children end - def self.read(io : IO::FileDescriptor, offset) + def self.read(io : IO) : Array(Abbrev) abbreviations = [] of Abbrev - io.seek(io.tell + offset) loop do code = DWARF.read_unsigned_leb128(io) break if code == 0 diff --git a/src/crystal/dwarf/info.cr b/src/crystal/dwarf/info.cr index e4799d9af8bd..8fb26a6e2149 100644 --- a/src/crystal/dwarf/info.cr +++ b/src/crystal/dwarf/info.cr @@ -50,10 +50,6 @@ module Crystal alias Value = Bool | Int32 | Int64 | Slice(UInt8) | String | UInt16 | UInt32 | UInt64 | UInt8 | UInt128 - def read_abbreviations(io) - @abbreviations = Abbrev.read(io, debug_abbrev_offset) - end - def each(&) end_offset = @offset + @unit_length attributes = [] of {AT, FORM, Value} @@ -62,7 +58,7 @@ module Crystal code = DWARF.read_unsigned_leb128(@io) attributes.clear - if abbrev = abbreviations[code &- 1]? # abbreviations.find { |a| a.code == abbrev } + if abbrev = @abbreviations.try &.[code &- 1]? # @abbreviations.try &.find { |a| a.code == abbrev } abbrev.attributes.each do |attr| value = read_attribute_value(attr.form, attr) attributes << {attr.at, attr.form, value} diff --git a/src/exception/call_stack/elf.cr b/src/exception/call_stack/elf.cr index 51d565528577..c4d90a6e879b 100644 --- a/src/exception/call_stack/elf.cr +++ b/src/exception/call_stack/elf.cr @@ -71,14 +71,24 @@ struct Exception::CallStack @@dwarf_line_numbers = Crystal::DWARF::LineNumbers.new(io, sh.size, base_address, strings, line_strings) end + abbrevs_tables = image.read_section?(".debug_abbrev") do |sh, io| + all = {} of Int64 => Array(Crystal::DWARF::Abbrev) + while (offset = io.pos - sh.offset) < sh.size + all[offset] = Crystal::DWARF::Abbrev.read(io) + end + all + end + image.read_section?(".debug_info") do |sh, io| names = [] of {LibC::SizeT, LibC::SizeT, String} while (offset = io.pos - sh.offset) < sh.size info = Crystal::DWARF::Info.new(io, offset) - image.read_section?(".debug_abbrev") do |sh, io| - info.read_abbreviations(io) + if abbrevs_tables + if abbreviations = abbrevs_tables[info.debug_abbrev_offset]? + info.abbreviations = abbreviations + end end parse_function_names_from_dwarf(info, strings, line_strings) do |low_pc, high_pc, name| diff --git a/src/exception/call_stack/mach_o.cr b/src/exception/call_stack/mach_o.cr index 7dc9d72666f3..a2eb48ba83db 100644 --- a/src/exception/call_stack/mach_o.cr +++ b/src/exception/call_stack/mach_o.cr @@ -27,14 +27,24 @@ struct Exception::CallStack @@dwarf_line_numbers = Crystal::DWARF::LineNumbers.new(io, sh.size, strings: strings, line_strings: line_strings) end + abbrevs_tables = mach_o.read_section?("__debug_abbrev") do |sh, io| + all = {} of Int64 => Array(Crystal::DWARF::Abbrev) + while (offset = io.pos - sh.offset) < sh.size + all[offset] = Crystal::DWARF::Abbrev.read(io) + end + all + end + mach_o.read_section?("__debug_info") do |sh, io| names = [] of {LibC::SizeT, LibC::SizeT, String} while (offset = io.pos - sh.offset) < sh.size info = Crystal::DWARF::Info.new(io, offset) - mach_o.read_section?("__debug_abbrev") do |sh, io| - info.read_abbreviations(io) + if abbrevs_tables + if abbreviations = abbrevs_tables[info.debug_abbrev_offset]? + info.abbreviations = abbreviations + end end parse_function_names_from_dwarf(info, strings, line_strings) do |low_pc, high_pc, name|