Class: WORF::DebugLine

Inherits:
Object
  • Object
show all
Defined in:
lib/worf.rb

Defined Under Namespace

Classes: FileName, Info, Registers

Instance Method Summary collapse

Constructor Details

#initialize(io, section, head_pos) ⇒ DebugLine

Returns a new instance of DebugLine.



276
277
278
279
280
# File 'lib/worf.rb', line 276

def initialize io, section, head_pos
  @io                  = io
  @section             = section
  @head_pos            = head_pos
end

Instance Method Details

#infoObject



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# 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