Initial commit

parents
import struct
import sys
def read_nullterminated_string(f):
filename = ''
while True:
byte, = struct.unpack('B', f.read(1))
if byte == 0:
break
filename += chr(byte)
return filename
def read_unsigned_leb128(f):
result = 0
shift = 0
while True:
byte, = struct.unpack('B', f.read(1))
result |= (byte & 0x7f) << shift
if byte & 0x80 == 0:
break
shift += 7
return result
def read_signed_leb128(f):
result = 0
shift = 0
size = 64
while True:
byte, = struct.unpack('B', f.read(1))
result |= (byte & 0x7f) << shift
shift += 7
if byte & 0x80 == 0:
break
if (shift < size) and (byte & 0x40):
result |= (~0 << shift)
return result
def read_debug_lineinfo_block(f):
offset = f.tell()
# Header
length, dwarf_version, prologue_length, \
minimum_instruction_length, initial_is_stmt_value, \
line_base, line_range, opcode_base = struct.unpack('=IHI2BbBb', f.read(15))
maximum_operations_per_instruction = 1
std_opcode_lengths = list(struct.unpack('=12B', f.read(12)))
#print('Offset: {:#x}'.format(offset))
#print('Length: {}'.format(length))
#print('DWARF Version: {}'.format(dwarf_version))
##print(line_base, line_range)
#print('')
#print('The Directory Table (offset {:#x})'.format(f.tell()))
directories = []
no = 0
while True:
byte, = struct.unpack('B', f.read(1))
if byte == 0:
break
f.seek(-1, 1)
no += 1
directory = read_nullterminated_string(f)
directories.append(directory)
#print('{} {}'.format(no, directory))
#print('')
#print('The File Name Table (offset {:#x})'.format(f.tell()))
files = []
no = 0
while True:
byte, = struct.unpack('B', f.read(1))
if byte == 0:
break
f.seek(-1, 1)
no += 1
filename = read_nullterminated_string(f)
files.append(filename)
directory_id, time, size = read_unsigned_leb128(f), read_unsigned_leb128(f), read_unsigned_leb128(f)
#print('{} {} {} {}'.format(no, filename, directory_id, time, size))
DW_EXTENDED_OP, \
DW_LNS_copy, DW_LNS_advance_pc, DW_LNS_advance_line, DW_LNS_set_file, DW_LNS_set_column, DW_LNS_negate_stmt, \
DW_LNS_set_basic_block, DW_LNS_const_add_pc, DW_LNS_fixed_advance_pc, \
DW_LNS_set_prologue_end, DW_LNS_set_epilogue_begin, DW_LNS_set_isa = range(13)
DW_LNE_end_sequence, DW_LNE_set_address, DW_LNE_define_file, DW_LNE_set_discriminator = range(1, 5)
matrix = []
#print('')
#print('Line Number Statements:')
while f.tell() < offset + length:
address = 0
op_index = 0
file, line, column = 1, 1, 0
is_stmt = initial_is_stmt_value
basic_block = False
end_sequence = False
prologue_end, epilogue_begin = False, False
isa = 0
discriminator = 0
while not end_sequence:
#print(' [{:#010x}] '.format(f.tell()), end='')
opcode, = struct.unpack('B', f.read(1))
if opcode == DW_LNS_copy:
#print('Copy')
# append to matrix
matrix.append([file, line, column, address, is_stmt, prologue_end, epilogue_begin])
discriminator = 0
basic_block = False
prologue_end = False
epilogue_begin = False
elif opcode == DW_LNS_advance_pc:
operation_advance = read_unsigned_leb128(f)
address_advance = int((minimum_instruction_length * (op_index + operation_advance))
/ maximum_operations_per_instruction)
address += address_advance
op_index = (op_index + operation_advance) % maximum_operations_per_instruction
#print('Advance PC by {} to {:#x}'.format(address_advance, address))
elif opcode == DW_LNS_advance_line:
line_advance = read_signed_leb128(f)
line += line_advance
#print('Advance Line by {} to {}'.format(line_advance, line))
elif opcode == DW_LNS_set_file:
file = read_unsigned_leb128(f)
#print('Set file to {} (id {})'.format(files[file-1], file))
elif opcode == DW_LNS_set_column:
column = read_unsigned_leb128(f)
#print('Set column to {}'.format(column))
elif opcode == DW_LNS_negate_stmt:
#print('Negate stmt')
is_stmt = ~is_stmt
elif opcode == DW_LNS_set_basic_block:
#print('Set basic_block to true')
basic_block = True
elif opcode == DW_LNS_const_add_pc:
adjusted_opcode = 255 - opcode_base
operation_advance = int(adjusted_opcode / line_range)
address_advance = int((minimum_instruction_length * (op_index + operation_advance))
/ maximum_operations_per_instruction)
address += address_advance
op_index = (op_index + operation_advance) % maximum_operations_per_instruction
#print('Const advance Address by {} to {:#x}'
# .format(address_advance, address))
elif opcode == DW_LNS_fixed_advance_pc:
address_advance, = struct.unpack('H', f.read(2))
address += address_advance
#print('Fixed advance Address by {} to {:#x}'
# .format(address_advance, address))
elif opcode == DW_LNS_set_prologue_end:
#print('Set prologue_end to true')
prologue_end = True
elif opcode == DW_LNS_set_epilogue_begin:
#print('Set epilogue begin to true')
epilogue_begin = True
elif opcode == DW_LNS_set_isa:
isa = read_unsigned_leb128(f)
#print('Set isa register to {}'.format(isa))
elif opcode == DW_EXTENDED_OP:
operation_size = read_unsigned_leb128(f)
extended_opcode, = struct.unpack('B', f.read(1))
#print('Extended opcode {}: '.format(extended_opcode), end='')
if extended_opcode == DW_LNE_end_sequence:
end_sequence = True
# append to matrix
matrix.append([file, line, column, address, is_stmt, prologue_end, epilogue_begin])
#print('End of Sequence')
elif extended_opcode == DW_LNE_set_address:
address, = struct.unpack('P', f.read(8))
#print('set Address to {:#x}'.format(address))
op_index = 0
elif extended_opcode == DW_LNE_define_file:
raise RuntimeError('DW_LNE_define_file is not implemented yet')
elif extended_opcode == DW_LNE_set_discriminator:
discriminator = read_unsigned_leb128(f)
#print('Set discriminator register to {}'.format(discriminator))
else:
raise RuntimeError('Illegal instruction.')
else:
adjusted_opcode = opcode - opcode_base
#print('Special opcode {}: '.format(adjusted_opcode), end='')
operation_advance = int(adjusted_opcode / line_range)
address_advance = int((minimum_instruction_length * (op_index + operation_advance))
/ maximum_operations_per_instruction)
address += address_advance
op_index = (op_index + operation_advance) % maximum_operations_per_instruction
line_advance = line_base + (adjusted_opcode % line_range)
line += line_advance
#print('advance Address by {} to {:#x} and Line by {} to {}'
# .format(address_advance, address, line_advance, line))
# append to matrix
matrix.append([file, line, column, address, is_stmt, prologue_end, epilogue_begin])
basic_block, prologue_end, epilogue_begin, discriminator = False, False, False, 0
return [directories, files, matrix]
f = open(sys.argv[1], "rb")
try:
f.seek(0, 2)
filesize = f.tell()
f.seek(0)
while f.tell() < filesize:
#print('------------------------------------------------------------')
#print('')
#print('')
directories, files, matrix = read_debug_lineinfo_block(f)
#print('')
for line in matrix:
print('{}:{}:{} {:#x}'.format(files[line[0]-1], line[1], line[2], line[3]))
#print('')
except IOError:
raise
except RuntimeError:
raise
except Exception:
raise
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment