def guess_from_fdr(filename): fdr = FDRLoader(filename) rec = next(iter(fdr)) if isinstance(rec, Comment): t = WORD_SPEC.unpack(rec.data[0:4])[0] if t == 0x424f4c42: # Version marker v = struct.unpack(ENDIAN + WORD_CHAR * 4, rec.data[4:]) return guess_from_version(v) return None
def main(): args = parse_arguments() if args.struct_file is None: args.struct_file = guess_from_fdr(args.input) print('[Using struct file %s]' % args.struct_file) if args.struct_file is None: print( 'Could not determine struct file from GCABI in FDR, provide --struct-file= argument' ) defs = load_data_definitions(args.struct_file) state_xml = parse_rng_file(args.rules_file) state_map = state_xml.lookup_domain('VIVS') cmdstream_xml = parse_rng_file(args.cmdstream_file) fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE') cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE') cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map) #print(fe_opcode.values_by_value[1].name) #print(format_path(cmdstream_map.lookup_address(0,('LOAD_STATE','FE_OPCODE')))) fdr = FDRLoader(args.input) global options options = args def handle_comment(f, val, depth): '''Annotate value with a comment''' if not depth: return None parent = depth[-1][0] field = depth[-1][1] parent_type = parent.type['name'] # Show names for features and minor feature bits if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY': if field == 'chipMinorFeatures': field = 'chipMinorFeatures0' if field in state_xml.types and isinstance(state_xml.types[field], BitSet): feat = state_xml.types[field] active_feat = [ bit.name for bit in feat.bitfields if bit.extract(val.value) ] return ' '.join(active_feat) elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY': if field == 'address': # annotate addresses with unique identifier return format_addr(val.value) def handle_pointer(f, ptr, depth): parent = depth[-1][0] field = depth[-1][1] if ptr.type in ['_gcoCMDBUF', '_gcoCONTEXT', '_gcsQUEUE']: s = extract_structure(fdr, ptr.addr, defs, ptr.type, resolver=resolver) f.write('&(%s)0x%x' % (ptr.type, ptr.addr)) dump_structure(f, s, handle_pointer, handle_comment, depth) return elif field == 'logical' and ptr.addr != 0: # Command stream if parent.type['name'] == '_gcoCMDBUF': f.write('&(uint32[])0x%x' % (ptr.addr)) dump_command_buffer( f, fdr, ptr.addr + parent.members['startOffset'].value, ptr.addr + parent.members['offset'].value, depth, state_map, cmdstream_info) return if parent.type[ 'name'] == '_gcoCONTEXT' and options.show_context_commands: f.write('&(uint32[])0x%x' % (ptr.addr)) dump_command_buffer( f, fdr, ptr.addr, ptr.addr + parent.members['bufferSize'].value, depth, state_map, cmdstream_info) return elif parent.type[ 'name'] == '_gcoCONTEXT' and field == 'map' and ptr.addr != 0 and options.show_state_map: f.write('&(uint32[])0x%x' % (ptr.addr)) dump_context_map(f, fdr, ptr.addr, ptr.addr + parent.members['stateCount'].value * 4, depth, state_map) return elif parent.type[ 'name'] == '_gcoCONTEXT' and field == 'buffer' and ptr.addr != 0 and options.show_context_buffer: # Equivalent to gcoCONTEXT.map f.write('&(uint32[])0x%x' % (ptr.addr)) dump_command_buffer(f, fdr, ptr.addr, ptr.addr + parent.members['bufferSize'].value, depth, state_map, cmdstream_info) return print_address(f, ptr, depth) f = sys.stdout thread_id = Counter() def thread_name(rec): return '[thread %i]' % thread_id[rec.parameters['thread'].value] for seq, rec in enumerate(fdr): if isinstance(rec, Event): # Print events as they appear in the fdr f.write(('[seq %i] ' % seq) + thread_name(rec) + ' ') params = rec.parameters if rec.event_type == 'MMAP_AFTER': f.write( 'mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n' % (params['addr'].value, params['length'].value, params['prot'].value, params['flags'].value, params['offset'].value, params['ret'].value)) elif rec.event_type == 'MUNMAP_AFTER': f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' % (params['addr'].value, params['length'].value, params['ret'].value)) elif rec.event_type == 'IOCTL_BEFORE': # addr, length, prot, flags, offset if params['request'].value == IOCTL_GCHAL_INTERFACE: ptr = params['ptr'].value inout = vivante_ioctl_data_t.unpack( fdr[ptr:ptr + vivante_ioctl_data_t.size]) f.write('in=') resolver = HalResolver('in') s = extract_structure(fdr, inout[0], defs, '_gcsHAL_INTERFACE', resolver=resolver) dump_structure(f, s, handle_pointer, handle_comment) f.write('\n') else: f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value) elif rec.event_type == 'IOCTL_AFTER': if params['request'].value == IOCTL_GCHAL_INTERFACE: ptr = params['ptr'].value inout = vivante_ioctl_data_t.unpack( fdr[ptr:ptr + vivante_ioctl_data_t.size]) f.write('out=') resolver = HalResolver('out') s = extract_structure(fdr, inout[2], defs, '_gcsHAL_INTERFACE', resolver=resolver) dump_structure(f, s, handle_pointer, handle_comment) f.write('\n') f.write( '/* ================================================ */\n' ) else: f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value) else: f.write('unhandled event ' + rec.event_type + '\n') elif isinstance(rec, Comment): t = WORD_SPEC.unpack(rec.data[0:4])[0] if t == 0x594e4f50: v = struct.unpack(ENDIAN + WORD_CHAR * 3, rec.data[4:]) print('[end of frame %d: %d.%09d]' % v) elif t == 0x424f4c42: v = struct.unpack(ENDIAN + WORD_CHAR * 4, rec.data[4:]) print('[driver version %d.%d.%d.%d]' % v)
def main(): args = parse_arguments() if args.struct_file is None: args.struct_file = guess_from_fdr(args.input) print('[Using struct file %s]' % args.struct_file) if args.struct_file is None: print('Could not determine struct file from GCABI in FDR, provide --struct-file= argument') defs = load_data_definitions(args.struct_file) state_xml = parse_rng_file(args.rules_file) state_map = state_xml.lookup_domain('VIVS') cmdstream_xml = parse_rng_file(args.cmdstream_file) fe_opcode = cmdstream_xml.lookup_type('FE_OPCODE') cmdstream_map = cmdstream_xml.lookup_domain('VIV_FE') cmdstream_info = CmdStreamInfo(fe_opcode, cmdstream_map) txdesc_xml = parse_rng_file(args.txdesc_file) txdesc_map = txdesc_xml.lookup_domain('TEXDESC') fdr = FDRLoader(args.input) global options options = args def handle_comment(f, val, depth): '''Annotate value with a comment''' if not depth: return None parent = depth[-1][0] field = depth[-1][1] parent_type = parent.type['name'] # Show names for features and minor feature bits if parent_type == '_gcsHAL_QUERY_CHIP_IDENTITY': if field == 'chipMinorFeatures': field = 'chipMinorFeatures0' if field in state_xml.types and isinstance(state_xml.types[field], BitSet): feat = state_xml.types[field] active_feat = [bit.name for bit in feat.bitfields if bit.extract(val.value)] return ' '.join(active_feat) elif parent_type == '_gcsHAL_LOCK_VIDEO_MEMORY': if field == 'address': # annotate addresses with unique identifier return tracking.format_addr(val.value) elif parent_type == '_gcsUSER_MEMORY_DESC': if field == 'physical': # annotate addresses with unique identifier return tracking.format_addr(val.value) elif parent_type == '_gcsHAL_SIGNAL': if field == 'signal': return 'id = %d' % val.value if field == 'node': if val.value in tracking.nodes: return tracking.nodes[val.value].name def handle_pointer(f, ptr, depth): parent = depth[-1][0] field = depth[-1][1] if ptr.type in ['_gcoCMDBUF','_gcsQUEUE']: s = extract_structure(fdr, ptr.addr, defs, ptr.type, resolver=resolver) f.write('&(%s)0x%x' % (ptr.type,ptr.addr)) dump_structure(f, s, handle_pointer, handle_comment, depth) return elif field == 'logical' and ptr.addr != 0: # Command stream if parent.type['name'] == '_gcoCMDBUF': f.write('&(uint32[])0x%x' % (ptr.addr)) dump_command_buffer(f, fdr, ptr.addr + parent.members['startOffset'].value, ptr.addr + parent.members['offset'].value, depth, state_map, cmdstream_info, tracking, txdesc_map) return print_address(f, ptr, depth) f = sys.stdout tracking = DriverState(defs) for seq,rec in enumerate(fdr): if isinstance(rec, Event): # Print events as they appear in the fdr if not args.summary: f.write(('[seq %i] ' % seq) + tracking.thread_name(rec) + ' ') params = rec.parameters if rec.event_type == 'MMAP_BEFORE': # ignore pass elif rec.event_type == 'MMAP_AFTER': f.write('mmap addr=0x%08x length=0x%08x prot=0x%08x flags=0x%08x offset=0x%08x = 0x%08x\n' % ( params['addr'].value, params['length'].value, params['prot'].value, params['flags'].value, params['offset'].value, params['ret'].value)) elif rec.event_type == 'MUNMAP_AFTER': f.write('munmap addr=0x%08x length=0x%08x = 0x%08x\n' % ( params['addr'].value, params['length'].value, params['ret'].value)) elif rec.event_type == 'IOCTL_BEFORE': # addr, length, prot, flags, offset if params['request'].value == IOCTL_GCHAL_INTERFACE: ptr = params['ptr'].value inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size]) if not args.summary: f.write('in=') resolver = HalResolver('in') s = extract_structure(fdr, inout[0], defs, '_gcsHAL_INTERFACE', resolver=resolver) tracking.handle_gcin(rec.parameters['thread'].value, s, extract_meta(fdr, defs, resolver, s)) if not args.summary or s.members['command'].name == 'gcvHAL_COMMIT': dump_structure(f, s, handle_pointer, handle_comment) f.write('\n') else: f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value) elif rec.event_type == 'IOCTL_AFTER': if params['request'].value == IOCTL_GCHAL_INTERFACE: ptr = params['ptr'].value inout = vivante_ioctl_data_t.unpack(fdr[ptr:ptr+vivante_ioctl_data_t.size]) if not args.summary: f.write('out=') resolver = HalResolver('out') s = extract_structure(fdr, inout[2], defs, '_gcsHAL_INTERFACE', resolver=resolver) tracking.handle_gcout(rec.parameters['thread'].value, s) if not args.summary: dump_structure(f, s, handle_pointer, handle_comment) f.write('\n') f.write('/* ================================================ */\n') else: f.write('Unknown Vivante ioctl %i\n' % rec.parameters['request'].value) else: f.write('unhandled event ' + rec.event_type + '\n') elif isinstance(rec, Comment): t = WORD_SPEC.unpack(rec.data[0:4])[0] if t == 0x594e4f50: v = struct.unpack(ENDIAN + WORD_CHAR * 3, rec.data[4:]) print('[end of frame %d: %d.%09d]' % v) elif t == 0x424f4c42: v = struct.unpack(ENDIAN + WORD_CHAR * 4, rec.data[4:]) print('[driver version %d.%d.%d.%d]' % v)