Skip to content

Commit

Permalink
Debug::DWARF: more decoding optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Feb 12, 2019
1 parent d19e070 commit 8c5f4ca
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 31 deletions.
20 changes: 13 additions & 7 deletions src/callstack.cr
Expand Up @@ -250,7 +250,7 @@ struct CallStack
attributes.each do |(at, form, value)|
case at
when Debug::DWARF::AT::DW_AT_name
value = strings.try(&.decode(value.as(UInt32 | UInt64))) if form.strp?
value = strings.try(&.decode(value.as(UInt32 | UInt64).to_u64)) if form.strp?
name = value.as(String)
when Debug::DWARF::AT::DW_AT_low_pc
low_pc = value.as(LibC::SizeT)
Expand Down Expand Up @@ -279,14 +279,17 @@ struct CallStack
end

strings = mach_o.read_section?("__debug_str") do |sh, io|
Debug::DWARF::Strings.new(io, sh.offset)
Debug::DWARF::Strings.new(io, sh.offset.to_u64, sh.size.to_u64)
end

mach_o.read_section?("__debug_info") do |sh, io|
names = [] of {LibC::SizeT, LibC::SizeT, String}

while io.tell - sh.offset < sh.size
offset = io.tell - sh.offset
while true
pos = io.pos
offset = pos - sh.offset
break unless offset < sh.size

info = Debug::DWARF::Info.new(io, offset)

mach_o.read_section?("__debug_abbrev") do |sh, io|
Expand Down Expand Up @@ -381,14 +384,17 @@ struct CallStack
end

strings = elf.read_section?(".debug_str") do |sh, io|
Debug::DWARF::Strings.new(io, sh.offset)
Debug::DWARF::Strings.new(io, sh.offset, sh.size)
end

elf.read_section?(".debug_info") do |sh, io|
names = [] of {LibC::SizeT, LibC::SizeT, String}

while io.tell - sh.offset < sh.size
offset = io.tell - sh.offset
while true
pos = io.pos
offset = pos - sh.offset
break if offset < sh.size

info = Debug::DWARF::Info.new(io, offset)

elf.read_section?(".debug_abbrev") do |sh, io|
Expand Down
10 changes: 5 additions & 5 deletions src/debug/dwarf/info.cr
Expand Up @@ -4,9 +4,9 @@ require "./abbrev"
module Debug
module DWARF
struct Info
property unit_length : UInt32 | UInt64
property unit_length : UInt64
property version : UInt16
property debug_abbrev_offset : UInt32 | UInt64
property debug_abbrev_offset : UInt64
property address_size : UInt8
property! abbreviations : Array(Abbrev)

Expand All @@ -17,7 +17,7 @@ module Debug
def initialize(@io : IO::FileDescriptor, @offset)
@ref_offset = offset

@unit_length = @io.read_bytes(UInt32)
@unit_length = @io.read_bytes(UInt32).to_u64
if @unit_length == 0xffffffff
@dwarf64 = true
@unit_length = @io.read_bytes(UInt64)
Expand Down Expand Up @@ -118,7 +118,7 @@ module Debug
when FORM::RefSig8
@io.read_bytes(UInt64)
when FORM::String
@io.gets('\0').to_s.chomp('\0')
@io.gets('\0', chomp: true).to_s
when FORM::Strp
read_ulong
when FORM::Indirect
Expand All @@ -133,7 +133,7 @@ module Debug
if @dwarf64
@io.read_bytes(UInt64)
else
@io.read_bytes(UInt32)
@io.read_bytes(UInt32).to_u64
end
end
end
Expand Down
13 changes: 8 additions & 5 deletions src/debug/dwarf/line_numbers.cr
Expand Up @@ -219,10 +219,13 @@ module Debug
filename: {} of String => Int32,
}

while (@io.tell - @offset) < size
sequence = Sequence.new
while true
pos = @io.tell
offset = pos - @offset
break unless offset < size

sequence.offset = @io.tell - @offset
sequence = Sequence.new
sequence.offset = offset
sequence.unit_length = @io.read_bytes(UInt32)
sequence.version = @io.read_bytes(UInt16)
sequence.header_length = @io.read_bytes(UInt32)
Expand Down Expand Up @@ -255,15 +258,15 @@ module Debug

private def read_directory_table(sequence)
loop do
name = @io.gets('\0').to_s.chomp('\0')
name = @io.gets('\0', chomp: true).to_s
break if name.empty?
sequence.include_directories << name
end
end

private def read_filename_table(sequence)
loop do
name = @io.gets('\0').to_s.chomp('\0')
name = @io.gets('\0', chomp: true).to_s
break if name.empty?
dir = DWARF.read_unsigned_leb128(@io)
time = DWARF.read_unsigned_leb128(@io)
Expand Down
19 changes: 16 additions & 3 deletions src/debug/dwarf/strings.cr
@@ -1,12 +1,25 @@
module Debug
module DWARF
struct Strings
def initialize(@io : IO::FileDescriptor, @offset : UInt32 | UInt64)
def initialize(@io : IO::FileDescriptor, @offset : UInt64, @size : UInt64)
# Read a good chunk of bytes to decode strings faster
# (avoid seeking/reading the IO too many times)
@buffer = Bytes.new(Math.max(16384, @size))
pos = @io.pos
@io.read_fully(@buffer)
@io.pos = pos
end

def decode(strp)
def decode(strp : UInt64)
# See if we can read it from the buffer
if strp < @buffer.size
index = @buffer.index('\0'.ord, offset: strp)
return String.new(@buffer[strp, index - strp]) if index
end

# If not, try directly from the IO
@io.seek(@offset + strp) do
@io.gets('\0').to_s.chomp('\0')
@io.gets('\0', chomp: true).to_s
end
end
end
Expand Down
20 changes: 10 additions & 10 deletions src/debug/elf.cr
Expand Up @@ -117,13 +117,13 @@ module Debug
property! name : UInt32
property! type : Type
property! flags : Flags
property! addr : UInt32 | UInt64
property! offset : UInt32 | UInt64
property! size : UInt32 | UInt64
property! addr : UInt64
property! offset : UInt64
property! size : UInt64
property! link : UInt32
property! info : UInt32
property! addralign : UInt32 | UInt64
property! entsize : UInt32 | UInt64
property! addralign : UInt64
property! entsize : UInt64
end

class Error < Exception
Expand All @@ -133,9 +133,9 @@ module Debug
property! type : Type
property! machine : Machine
property! version : UInt32
property! entry : UInt32 | UInt64
property! phoff : UInt32 | UInt64
property! shoff : UInt32 | UInt64
property! entry : UInt64
property! phoff : UInt64
property! shoff : UInt64
property! flags : UInt32
property! ehsize : UInt16
property! phentsize : UInt16
Expand Down Expand Up @@ -201,7 +201,7 @@ module Debug
def sh_name(index)
sh = section_headers[shstrndx]
@io.seek(sh.offset + index) do
@io.gets('\0').to_s.chomp('\0')
@io.gets('\0', chomp: true).to_s
end
end

Expand All @@ -226,7 +226,7 @@ module Debug

private def read_ulong
case ident.klass
when Klass::ELF32 then @io.read_bytes(UInt32, endianness)
when Klass::ELF32 then @io.read_bytes(UInt32, endianness).to_u64
when Klass::ELF64 then @io.read_bytes(UInt64, endianness)
else raise Error.new("Unsupported")
end
Expand Down
2 changes: 1 addition & 1 deletion src/debug/mach_o.cr
Expand Up @@ -458,7 +458,7 @@ module Debug

if nlist.strx > 0
@io.seek(symtab.stroff + nlist.strx) do
nlist.name = @io.gets('\0').to_s.chomp('\0')
nlist.name = @io.gets('\0', chomp: true).to_s
end
end

Expand Down

0 comments on commit 8c5f4ca

Please sign in to comment.