class WORF::DebugLine

Constants

FileName
Info

Public Class Methods

new(io, section, head_pos) click to toggle source
# File lib/worf.rb, line 276
def initialize io, section, head_pos
  @io                  = io
  @section             = section
  @head_pos            = head_pos
end

Public Instance Methods

info() click to toggle source
# File lib/worf.rb, line 282
def info
  include_directories = []
  file_names          = []
  matrix              = []

  @io.seek @head_pos + @section.offset, IO::SEEK_SET
  last_position = @head_pos + @section.offset + @section.size
  while @io.pos < last_position
    unit_length, dwarf_version = @io.read(6).unpack("LS")
    if dwarf_version != 4
      raise NotImplementedError, "Only DWARF4 rn #{dwarf_version}"
    end

    # we're just not handling 32 bit
    _, # prologue_length,
      min_inst_length,
      max_ops_per_inst,
      default_is_stmt,
      line_base,
      line_range,
      opcode_base = @io.read(4 + (1 * 6)).unpack("LCCCcCC")

    # assume address size is 8
    address_size = 8

    registers = Registers.new(default_is_stmt)

    @io.read(opcode_base - 1) #standard_opcode_lengths = @io.read(opcode_base - 1).bytes

    loop do
      str = @io.readline("\0").chomp("\0")
      break if "" == str
      include_directories << str
    end

    loop do
      fname = @io.readline("\0").chomp("\0")
      break if "" == fname

      directory_idx = WORF.unpackULEB128 @io
      last_mod      = WORF.unpackULEB128 @io
      length        = WORF.unpackULEB128 @io
      file_names << FileName.new(fname, directory_idx, last_mod, length)
    end

    loop do
      code = @io.readbyte
      case code
      when 0 # extended operands
        expected_size = WORF.unpackULEB128 @io
        raise if expected_size == 0

        cur_pos = @io.pos
        extended_code = @io.readbyte
        case extended_code
        when Constants::DW_LNE_end_sequence
          registers.end_sequence = true
          matrix << registers.dup
          break
        when Constants::DW_LNE_set_address
          registers.address = @io.read(address_size).unpack1("Q")
          registers.op_index = 0
        when Constants::DW_LNE_set_discriminator
          raise
        else
          raise "unknown extednded opcode #{extended_code}"
        end

        raise unless expected_size == (@io.pos - cur_pos)
      when Constants::DW_LNS_copy
        matrix << registers.dup
        registers.discriminator  = 0
        registers.basic_block    = false
        registers.prologue_end   = false
        registers.epilogue_begin = false
      when Constants::DW_LNS_advance_pc
        code = WORF.unpackULEB128 @io
        registers.address += (code * min_inst_length)
      when Constants::DW_LNS_advance_line
        registers.line += WORF.unpackSLEB128 @io
      when Constants::DW_LNS_set_file
        registers.file = WORF.unpackULEB128 @io
      when Constants::DW_LNS_set_column
        registers.column = WORF.unpackULEB128 @io
      when Constants::DW_LNS_negate_stmt
        registers.is_stmt = !registers.is_stmt
      when Constants::DW_LNS_set_basic_block
        registers.basic_block = true
      when Constants::DW_LNS_const_add_pc
        code = 255
        adjusted_opcode = code - opcode_base
        operation_advance = adjusted_opcode / line_range
        new_address = min_inst_length *
          ((registers.op_index + operation_advance) /
           max_ops_per_inst)

        new_op_index = (registers.op_index + operation_advance) % max_ops_per_inst

        registers.address += new_address
        registers.op_index = new_op_index
      when Constants::DW_LNS_fixed_advance_pc
        raise
      when Constants::DW_LNS_set_prologue_end
        registers.prologue_end = true
      when Constants::DW_LNS_set_epilogue_begin
        raise
      when Constants::DW_LNS_set_isa
        raise
      else
        adjusted_opcode = code - opcode_base
        operation_advance = adjusted_opcode / line_range
        new_address = min_inst_length *
          ((registers.op_index + operation_advance) /
           max_ops_per_inst)

        new_op_index = (registers.op_index + operation_advance) % max_ops_per_inst

        line_increment = line_base + (adjusted_opcode % line_range)

        registers.address += new_address
        registers.op_index = new_op_index
        registers.line += line_increment
        matrix << registers.dup

        registers.basic_block    = false
        registers.prologue_end   = false
        registers.epilogue_begin = false
        registers.discriminator  = 0
      end
    end
  end

  Info.new unit_length, dwarf_version, include_directories, file_names, matrix
end