Skip to content

Commit

Permalink
Merge pull request #7413 from asterite/opt/dwarf-decoding
Browse files Browse the repository at this point in the history
Optimize dwarf line numbers decoding
  • Loading branch information
asterite committed Feb 15, 2019
2 parents 27c07bf + 5e1d740 commit d83fe1c
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 48 deletions.
15 changes: 5 additions & 10 deletions src/callstack.cr
Expand Up @@ -223,10 +223,7 @@ struct CallStack
read_dwarf_sections unless @@dwarf_line_numbers
if ln = @@dwarf_line_numbers
if row = ln.find(pc)
path = ln.files[row.file]?
if dirname = ln.directories[row.directory]?
path = "#{dirname}/#{path}"
end
path = "#{row.directory}/#{row.file}"
return {path, row.line, row.column}
end
end
Expand Down Expand Up @@ -279,14 +276,13 @@ 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, sh.size)
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 (offset = io.pos - sh.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 +377,13 @@ 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 (offset = io.pos - sh.offset) < sh.size
info = Debug::DWARF::Info.new(io, offset)

elf.read_section?(".debug_abbrev") do |sh, io|
Expand Down
2 changes: 1 addition & 1 deletion src/debug/dwarf/info.cr
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 Down
45 changes: 12 additions & 33 deletions src/debug/dwarf/line_numbers.cr
Expand Up @@ -115,8 +115,8 @@ module Debug
record Row,
address : UInt64,
op_index : UInt32,
directory : Int32,
file : Int32,
directory : String,
file : String,
line : Int32,
column : Int32,
end_sequence : Bool
Expand Down Expand Up @@ -168,19 +168,11 @@ module Debug
# reduce the memory usage of repeating a String many times.
getter matrix : Array(Array(Row))

# The array of indexed directory paths.
getter directories : Array(String)

# The array of indexed file names.
getter files : Array(String)

@offset : LibC::OffT

def initialize(@io : IO::FileDescriptor, size)
@offset = @io.tell
@matrix = Array(Array(Row)).new
@directories = [] of String
@files = [] of String
decode_sequences(size)
end

Expand Down Expand Up @@ -213,10 +205,13 @@ module Debug

# Decodes the compressed matrix of addresses to line numbers.
private def decode_sequences(size)
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 @@ -249,15 +244,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 Expand Up @@ -370,8 +365,8 @@ module Debug
row = Row.new(
registers.address,
registers.op_index,
register_directory(path),
register_filename(file[0]),
path,
file[0],
registers.line.to_i,
registers.column.to_i,
registers.end_sequence
Expand All @@ -388,22 +383,6 @@ module Debug
@current_sequence_matrix = nil
end
end

private def register_filename(name)
if index = @files.index(name)
return index
end
@files << name
@files.size - 1
end

private def register_directory(name)
if index = @directories.index(name)
return index
end
@directories << name
@directories.size - 1
end
end
end
end
17 changes: 15 additions & 2 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 : UInt32 | UInt64, size)
# 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)
# 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
2 changes: 1 addition & 1 deletion src/debug/elf.cr
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 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 d83fe1c

Please sign in to comment.