def title_str(self): """ @brief Returns the title string of the object. @param[in] self Pointer to the current object """ return 'Operator ' + cu.hex(self.id) + ', ep_op_id ' + \ cu.hex(self.op_ep_id) + ', ' + self.cap_data.name
def read_kip_requests(self, display_all=False): ''' @brief This method shows kip request for ipc. If True is passed as an argument, all requests are displayed. If not, then only reasonable amount of them will be displayed @param[in] self Pointer to the current object ''' # Look up the debug information, unless we already have. if self._do_debuginfo_lookup: self._lookup_debuginfo() self._do_debuginfo_lookup = False self.formatter.section_start('KIP requests') # kip requests are held in linked list, thus read these entries kip_requests = [ req for req in self.parse_linked_list('L_kip_first_req', 'next') ] if not kip_requests: self.formatter.output('No KIP request present') else: # there might be lots of kip requests, thus display reasonable # number of them, unless ser asked to display all of them self.formatter.output('Pending KIP requests:\n') kip_str = '' max_to_display = 10 displayed = 0 apology = '' for req in kip_requests: kip_str += 'Connection ID: {0}\n'.format( cu.hex(req.get_member('con_id').value)) msg = self.debuginfo.get_enum( 'KIP_MSG_ID', req.get_member('msg_id').value)[0].replace( 'KIP_MSG_ID_', "") kip_str += 'Message ID: {0}\n'.format(msg) kip_str += 'Sequence number: {0}\n'.format( cu.hex(req.get_member('seq_nr').value)) req_context = req.get_member('context').value if req_context != 0: try: module_name = self.debuginfo.get_source_info( req_context).module_name except ct.BundleMissingError: module_name = ("No source information. " + "Bundle is missing.") kip_str += 'Context: {0}\n'.format(module_name) kip_str += '\n' displayed += 1 if displayed == max_to_display and not display_all: apology = ( '\n...\n{0} more requests. ' 'Pass True to the method to display ' 'all requests'.format(len(kip_requests) - displayed)) self.formatter.output(kip_str + apology) self.formatter.section_end() if self.chipdata.is_volatile(): self._do_debuginfo_lookup = True
def analyse_all_mmr(self): """ @brief This prints out all of the memory-mapped registers. Reg names are not precise (i.e. they are guesses), so this should only really be used in Interactive mode. @param[in] self Pointer to the current object """ # The whole memory-mapped register range mmr_range = list( range(Arch.dRegions['MMR'][0], Arch.dRegions['MMR'][1])) mmr_list = [] for i in mmr_range: try: # Tuple containing (address, register name, register contents) mmr_list.append((i, self.chipdata.get_reg_strict(i).name, self.chipdata.get_reg_strict(i).value)) except BaseException: # Not found pass self.formatter.section_start('All memory-mapped registers') for i in mmr_list: self.formatter.output( cu.hex(i[0]) + " " + i[1] + " " + cu.hex(i[2])) self.formatter.section_end()
def __str__(self): """ @brief Returns a tidy string representation of a timer object @param[in] self Pointer to the current object """ tf_str = "Timer " + cu.hex(self.id) + "\n" tf_str = tf_str + "Type: " + self.type + "\n" if self.type == 'strict': tf_str = tf_str + "Expiry time: " + cu.hex(self.latest_time) + "\n" else: tf_str = tf_str + "Earliest expiry: " + cu.hex(self.earliest_time) tf_str = tf_str + ", latest expiry: " + \ cu.hex(self.latest_time) + "\n" tf_str = tf_str + "Data pointer: " + cu.hex(self.data_pointer) + "\n" if self.timed_event_function is not None: tf_str = tf_str + "EventFunction: \n" temp_str = ' ' + str(self.timed_event_function) # Indent tf_str = tf_str + string.replace(temp_str, '\n', '\n ') # Indent tf_str = tf_str[:-4] # Remove indent from final newline return tf_str
def __str__(self): """ @brief To string function of the class. """ out_str = '{0:<20}{1:<10}{2:<15}{3:<15}\n'.format( cu.hex(self.device_address), self.length, cu.hex(self.file_address), cu.hex(self.file_id)) return out_str
def get_data_pm(self, address, length=0): """ @brief This method works in the exactly the same way as get_data(self, address, length = 0) method, but it returns data from PM region instead of DM. @param[in] self Pointer to the current object @param[in] address @param[in] length = 0 """ # We helpfully accept address as either a hex string or an integer try: # Try to convert address from a hex string to an integer address = int(address, 16) except TypeError: # Probably means address was already an integer pass address = cu.get_correct_addr(address, Arch.addr_per_word) if length == 0: mem_region = Arch.get_pm_region(address) else: mem_region = Arch.get_pm_region( address + cu.convert_byte_len_word(length, Arch.addr_per_word) - Arch.addr_per_word) try: if ('PMRAM' in mem_region) or ('PMCACHE' in mem_region) or \ ('SLT' in mem_region): if length == 0: return self.pm[address:address + Arch.addr_per_word][0] return tuple([ int(x) for x in self. pm[address:address + cu.convert_byte_len_word(length, Arch.addr_per_word)] ]) else: if length == 0: raise KeyError( "Key " + cu.hex(address + Arch.addr_per_word) + " is not a valid PM RAM address", address + Arch.addr_per_word) raise ct.OutOfRange( "Key " + cu.hex(address + cu.convert_byte_len_word( length, Arch.addr_per_word) - Arch.addr_per_word) + " is not a valid PM RAM address", address + cu.convert_byte_len_word(length, Arch.addr_per_word) - Arch.addr_per_word) except Exception as exception: if "Transport failure (Unable to read)" in exception: sys.stderr.write(str(exception)) raise ct.ChipNotPowered else: raise exception
def var_to_str(self, depth=0): """ @brief function used to convert a structure to a base_name: value \\n string @param[in] self Pointer to the current object @param[in] depth = 0 """ depth_str = " " * depth fv_str = "" if depth == 0: fv_str += "0x%08x " % self.address if self.members: if self.base_name == "": # Probably it was a pointer to something fv_str += (depth_str + self.name + ":\n") else: fv_str += (depth_str + self.base_name + ":\n") for member in self.members: fv_str += member.var_to_str(depth + 1) else: part_of_array = False if self.parent and \ isinstance(self.parent.array_len, int): # this member is an element of an array. part_of_array = True fv_str += (depth_str + "[" + str(self.parent.members.index(self)) + "]") # no need to add additional depth string. depth_str = "" if self.type_name in self.integer_names: # display integers in hex if not part_of_array: fv_str += (depth_str + self.base_name) fv_str += (": " + cu.hex(self.value) + "\n") elif "bool" in self.type_name: # buleans are displayed as true (1) or false (0). fv_str += (depth_str + self.base_name + ": ") if self.value != 0: fv_str += ("True\n") else: fv_str += ("False\n") elif "enum " in self.type_name: fv_str += depth_str + self._get_enum_name() else: # This is probably a pointer to something. if not part_of_array: if self.base_name != "": fv_str += (depth_str + self.base_name) else: fv_str += (depth_str + self.name) fv_str += (": " + cu.hex(self.value) + "\n") return fv_str
def desc_str(self): """ @brief Returns the description string of the endpoint. @param[in] self Pointer to the current object """ ep_str = "Address: " + cu.hex(self.address) + "\n" ep_str = ep_str + "Key: " + cu.hex(self.key) + "\n" # it's enough to check with one variable that it's the AudioEP if self.instance is not None: ep_str += "Device: " + str(self.hardware) + "\n" ep_str += "Instance: " + str(self.instance) + "\n" ep_str += "Channel: " + str(self.channel) + "\n" ep_str = ep_str + "is_real: " + \ str(self.is_real) + " can_be_closed: " + \ str(self.can_be_closed) + "\n" ep_str = ep_str + "can_be_destroyed: " + \ str(self.can_be_destroyed) + " destroy_on_disconnect: " + \ str(self.destroy_on_disconnect) + "\n" if self.con_id is not None: ep_str = ep_str + "Connection ID: " + str(self.con_id) + "\n" ep_str = ep_str + "connected_to: " try: connected_to = self.connected_to if connected_to is None: ep_str += "NULL\n" else: ep_str += cu.hex(connected_to.id) + \ "(" + connected_to.compact_name() + ") \n" except AttributeError: ep_str += ( "0x%08x is not a valid endpoint address\n" % self._connected_to ) ep_str += "ep_to_kick: " try: endpoint_to_kick = self.ep_to_kick if endpoint_to_kick is None: ep_str += "NULL\n" else: ep_str += cu.hex(endpoint_to_kick.id) + \ "(" + endpoint_to_kick.compact_name() + ") \n" except AttributeError: ep_str += ( "0x%08x is not a valid endpoint address\n" % self._ep_to_kick ) ep_str = ep_str + str(self.cbops) if self.is_state_type_equal_to_name: ep_str = ep_str + \ str(getattr(self, self.name)) return ep_str
def print_message_queue(self, msg_queue_var, display_buffer, display_messages): ''' @brief Displays the message queue. @param[in] self Pointer to the current object @param[in] msg_queue_var Pointer to a message queue variable. @param[in] display_buffer Flag to indicate if the underlying buffer should be further analysed. @param[in] display_messages Flag to indicate if message information is needed. ''' # buffers are used to store messages, this import buffer analysis for # analysing it if display_buffer: buffer_analysis = self.interpreter.get_analysis( "buffers", self.chipdata.processor) self.formatter.output('Queue ID: {0}'.format( msg_queue_var.get_member('queue_id').value)) self.formatter.output('Read counter: {0}'.format( msg_queue_var.get_member('message_read_counter').value)) self.formatter.output('Next message counter: {0}'.format( msg_queue_var.get_member('next_message_counter').value)) try: module_name = self.debuginfo.get_source_info( msg_queue_var.get_member('callback').value).module_name except ct.BundleMissingError: module_name = ("No source information. Bundle is missing.") self.formatter.output('Callback: {0}'.format(module_name)) buffer_pointer = msg_queue_var.get_member('cbuffer').value buffer_var = self.chipdata.cast(buffer_pointer, 'tCbuffer') self.formatter.output('Messages are stored in buffer at: {0}\n'.format( cu.hex(buffer_var.get_member('base_addr').value))) if display_messages: messages = self._get_buffer_messages(buffer_var) msg_str = 'Messages: \n' for (header, msg_id) in messages: if header == VALID_MSG_HEADER_EXT: msg_str += (' External message with ID: {0}\n'.format( cu.hex(msg_id))) elif header == VALID_MSG_HEADER_INT: msg_str += (' Internal message with ID: {0}\n'.format( cu.hex(msg_id))) self.formatter.output(msg_str + '\n') # if asked, print out the buffer associated with the queue if display_buffer: if msg_queue_var.get_member('cbuffer').value != 0: buffer_analysis.analyse_cbuffer(buffer_pointer) else: self.formatter.output('Message queue buffer is null \n')
def __str__(self): """ @brief To string function of the class. """ # update the table before printing. self._update_table() out_str = '\nIdentify: {0} Entries: {1}\n'.format( cu.hex(self.identify_field), self.num_of_entries) out_str += '{0:<20}{1:<10}{2:<15}{3:<15}\n'.format( 'Device address', 'length', 'file address', 'file elf_id') for entry in self.entries: out_str += str(entry) out_str += 'Checksum: {0}\n'.format(cu.hex(self.checksum)) return out_str
def __str__(self): # Special rule since you can't call hex() on None if self.address is not None: hex_addr = cu.hex(self.address) else: hex_addr = 'None' if self.value is not None: hex_val = cu.hex(self.value) else: hex_val = 'None' # Using str(x) here since it copes with the value being None return ('Name: ' + str(self.name) + '\n' + 'Address: ' + hex_addr + '\n' + 'Value: ' + hex_val + '\n')
def analyse_interrupt_stack_frames(self): """ @brief Prints out information about any interrupt frames on the stack. @param[in] self Pointer to the current object """ if self.stack_overflow_occurred(): raise ct.AnalysisError( "Can't analyse_interrupt_stack_frames(): a stack overflow has occurred." ) # Do a stack trace in order to refresh our memory # about what's on the stack. This will set self.interrupt_frames. self.get_stack_trace() for frame in self.interrupt_frames: self.formatter.section_start('Interrupt stack frame') isf = [] # list of strings for idx, entry in enumerate(frame): # Reverse the order again isf.insert(0, (self.int_frame_descriptors[idx].ljust(15) + " - " + cu.hex(entry))) self.formatter.output_list(isf) # Sanity check the frame. # Check that rintlink is valid. frame_saved_rintlink = frame[6] # rintlink could point to anywhere (not just a call instruction) # so calling is_saved_rlink() won't work. try: self.debuginfo.get_source_info(frame_saved_rintlink) except ct.InvalidPmAddress: self.formatter.alert( 'Saved rintlink in interrupt frame does not point to a ' 'code address - we may have been executing from cache!') self.formatter.section_end()
def get_oplist(self, mode='id'): """ @brief Returns a list of all operators in opmgr's oplist. 'Mode' selects which information to return: 'entry' - a list of op_entry elements 'id' - a list of operator IDs 'object' - a list of Operator objects (NB: could be slow) 'name' - a list of operator names and their ids @param[in] self Pointer to the current object @param[in] mode = 'id' """ op_entries = self._read_raw_oplist() if mode == 'entry': return op_entries elif mode == 'id': return [operator.get_member('id').value for operator in op_entries] elif mode == 'object': return [ operator_factory(operator, self) for operator in op_entries ] elif mode == 'name': return_list = [] for operator in op_entries: operator = operator_factory(operator, self) return_list.append(operator.cap_data.name + " " + cu.hex(operator.op_ep_id)) return return_list else: raise ct.Usage('Invalid oplist mode')
def desc_str(self): """ @brief Returns the description string of the endpoint. @param[in] self Pointer to the current object """ # Call the base class property function cannot be done otherwise ep_str = Endpoint.desc_str.fget(self) # pylint: disable=no-member tp_ptr_var = self.audio.get_member("timed_playback") if tp_ptr_var: # timed playback is enabled in the build timed_playback_ptr = tp_ptr_var.value if timed_playback_ptr != 0: # the endpoint has a timed playback instance. timed_playback_var = self.stream.chipdata.cast( addr=timed_playback_ptr, type_def="TIMED_PLAYBACK", elf_id=self.stream.debuginfo.get_kymera_debuginfo().elf_id ) ep_str = ep_str.replace( "timed_playback: " + cu.hex(timed_playback_ptr), str(timed_playback_var).replace("\n", "\n ") ) return ep_str
def analyse_aux_states(self): ''' @brief This method analyses the stated at which processors are at the time. @param[in] self Pointer to the current object ''' # Look up the debug information, unless we already have. if self._do_debuginfo_lookup: self._lookup_debuginfo() self._do_debuginfo_lookup = False self.formatter.section_start('Aux states') if self.aux_states_p == 0: self.formatter.output('No aux states information') self.formatter.section_end() if self.chipdata.is_volatile(): self._do_debuginfo_lookup = True return aux_states_array = self.chipdata.cast( self.aux_states_p, 'IPC_AUX_STATES').get_member('aux') all_states = self.debuginfo.get_enum('_IPC_SETUP_STATE', None) # This is states for every processor used, and it will be an array for processor in range(aux_states_array.array_len): aux_state = aux_states_array.__getitem__(processor) setup_state = aux_state.get_member('setup_state').value wakeup_time = aux_state.get_member('wakeup_time').value # Status state represents several possible flags. Find these flags # now if setup_state == 0x0000: active_states = ['SETUP_NONE'] else: active_states = [] for state, flag in all_states.items(): if state == 'IPC_SETUP_NONE': continue mask = 0x000F for _ in range(4): current_flag = setup_state & mask if current_flag == flag: active_states.append(state.replace("IPC_", "")) mask = mask << 4 state_str = '' for state in sorted(active_states): state_str += state + ', ' state_str = state_str[:-2] # remove last space and comma self.formatter.output( 'Aux state for processor p{0}:'.format(processor)) self.formatter.output(' Setup state: {0} - {1}'.format( cu.hex(setup_state), state_str)) self.formatter.output(' Wake-up time: {0}'.format(wakeup_time)) self.formatter.section_end() if self.chipdata.is_volatile(): self._do_debuginfo_lookup = True
def var_to_str(self, depth=0): """ @brief function used to convert a structure to a base_name: value \\n string @param[in] self Pointer to the current object @param[in] depth = 0 """ depth_str = " " * depth fv_str = "" if depth == 0: fv_str += "0x%08x " % self.address if (self.members is not None) and (self.members): if self.base_name == "": # Probably it was a pointer to something fv_str += (depth_str + self.name + ":\n") else: fv_str += (depth_str + self.base_name + ":\n") for member in self.members: fv_str += member.var_to_str(depth + 1) else: if "uint32" in self.type_name or \ "uint16" in self.type_name or \ "uint8" in self.type_name: fv_str += (depth_str + self.base_name + ": " + cu.hex(self.value) + "\n") elif "bool" in self.type_name: fv_str += (depth_str + self.base_name + ": ") if self.value != 0: fv_str += ("True\n") else: fv_str += ("False\n") elif self.parent and \ isinstance(self.parent.array_len, int): # vector fv_str += (depth_str + "[" + str(self.parent.members.index(self)) + "]: " + cu.hex(self.value) + "\n") elif "enum " in self.type_name: fv_str += depth_str + self._get_enum_name() else: if self.base_name != "": fv_str += (depth_str + self.base_name + ": " + cu.hex(self.value) + "\n") else: fv_str += (depth_str + self.name + ": " + cu.hex(self.value) + "\n") return fv_str
def _analyse_fifo(self, signal_block): ''' @brief This method shows content of fifo, if any pending actions are stored @param[in] self Pointer to the current object @param[in] signal_block - signal block that this fifo belongs to ''' self.formatter.section_start('FIFO information') fifo_p_array = signal_block.get_member('fifo').value # different fifo's are for different priority messages, but not all of # them might be used, thus only display those which had messages in # them at some point, which is indicated by the counter of maximum slots # taken for fifo_p in fifo_p_array: priority = fifo_p_array.index(fifo_p) fifo = self.chipdata.cast(fifo_p, 'IPC_SIGNAL_FIFO') if fifo.get_member('max').value == 0: self.formatter.output( 'FIFO of priority {0} have not been used'.format(priority)) # Nothing to do here anymore continue else: max_entries = fifo.get_member('entry').array_len self.formatter.output( 'FIFO of priority {0} information:\n'.format(priority)) numelts = fifo.get_member('numelts').value self.formatter.output( ' ' * 2 + 'Number of elements currently stored: {0}'.format(numelts)) self.formatter.output(' ' * 2 + 'Maximum number stored: {0}'.format( fifo.get_member('max').value)) if numelts > 0: # display pending elements read_idx_initial = fifo.get_member('rdidx').value for element_nr in range(numelts): read_idx = (read_idx_initial + element_nr) % max_entries element = fifo.get_member('entry').__getitem__( read_idx) self.formatter.output( ' ' * 4 + 'Fifo entry at position: {0}'.format(read_idx)) self.formatter.output( ' ' * 6 + 'Signal channel: {0}'.format( element.get_member('sigchan').value)) self.formatter.output(' ' * 6 + 'Sender: {0}'.format( element.get_member('sender').value)) self.formatter.output( ' ' * 6 + 'Signal ID: {0}'.format( element.get_member('sigid').value)) signal_ptr = element.get_member('sigreq').get_member( 'signal_ptr').value self.formatter.output( ' ' * 6 + 'Signal pointer: {0}'.format(cu.hex(signal_ptr))) self.formatter.section_end()
def analyse_messages(self, display_buffer=True, display_messages=False): ''' @brief this method analyses information about messages of ipc and prints them to formatter. if True parameter is passed to the function, buffer containing messages is analysed as well @param[in] self Pointer to the current object @param[in] display_buffer Flag to indicate if the underlying buffer should be further analysed. @param[in] display_messages Flag to indicate if message information is needed. ''' # Look up the debug information, unless we already have. if self._do_debuginfo_lookup: self._lookup_debuginfo() self._do_debuginfo_lookup = False self.formatter.section_start('IPC Messages Information') if self.ipc_msg_block_p == 0: self.formatter.output('No message information') self.formatter.section_end() if self.chipdata.is_volatile(): self._do_debuginfo_lookup = True return msg_block = self.chipdata.cast(self.ipc_msg_block_p, 'IPC_MESSAGE_BLOCK') self.formatter.output('Number of message channels used: {0}'.format( msg_block.get_member('number_of_channels').value)) self.formatter.output('Maximum message size: {0}'.format( msg_block.get_member('max_msg_sz').value)) self.formatter.output('Maximum number of messages: {0}'.format( msg_block.get_member('max_msgs').value)) # there will be array of msg channels, so read messages from them msg_cannel_p_array = msg_block.get_member('ipc_message_channel') self.formatter.output('IPC message channels:') # there might be more than one channel if more processors are used for msg_channel_p in msg_cannel_p_array: msg_channel = self.chipdata.cast(msg_channel_p.value, 'IPC_MESSAGE_CHANNEL') self.formatter.output(' Channel ID: {0}\n'.format( cu.hex(msg_channel.get_member('channel_id').value))) p0_to_px_msq_q = msg_channel.get_member('p0_2_px_message_queue') self.formatter.section_start('P0 to Px message queue:') self.print_message_queue(p0_to_px_msq_q, display_buffer, display_messages) self.formatter.section_end() px_to_p0_msg_q = msg_channel.get_member('px_2_p0_message_queue') self.formatter.section_start('Px to P0 message queue:') self.print_message_queue(px_to_p0_msg_q, display_buffer, display_messages) self.formatter.section_end() self.formatter.section_end() if self.chipdata.is_volatile(): self._do_debuginfo_lookup = True
def compact_name(self): """ @brief Returns a tidy and short string representation of an endpoint object @param[in] self Pointer to the current object """ ep_str = self.name.title() + " " + self.direction + " " + cu.hex(self.id) return ep_str
def output(self, string_to_output): """ @brief Normal body text. Lists/dictionaries will be compacted. @param[in] self Pointer to the current object @param[in] string_to_output """ with self.lock: self._log(cu.hex(string_to_output))
def __get_kick_table_op_string(self, kick_table): mask = kick_table.get_member("t_mask").value task_id = self.helper.chipdata.cast( kick_table.get_member("kt").get_member("ep").value, "BGINT").get_member("id").value operator = self.helper.get_operator_by_taskid(task_id) return " Operator " + cu.hex(operator.op_ep_id) + " " + operator.cap_data.name + \ " (mask: " + bin(mask) + ')\n'
def desc_str(self): """ @brief Returns the description string of the endpoint. @param[in] self Pointer to the current object """ ep_str = "Address: " + cu.hex(self.address) + "\n" ep_str = ep_str + "Key: " + cu.hex(self.key) + "\n" ep_str = ep_str + "is_real: " + \ str(self.is_real) + " can_be_closed: " + \ str(self.can_be_closed) + "\n" ep_str = ep_str + "can_be_destroyed: " + \ str(self.can_be_destroyed) + " destroy_on_disconnect: " + \ str(self.destroy_on_disconnect) + "\n" if self.con_id is not None: ep_str = ep_str + "Connection ID: " + str(self.con_id) + "\n" ep_str = ep_str + "connected_to: " if self.connected_to: ep_str += cu.hex(self.connected_to.id) + \ "(" + self.connected_to.compact_name() + ") \n" else: ep_str += "NULL\n" ep_str += "ep_to_kick: " if self.ep_to_kick: try: endpoint_to_kick = self.stream.get_endpoint_by_address( self.ep_to_kick ) ep_str += cu.hex(endpoint_to_kick.id) + \ "(" + endpoint_to_kick.compact_name() + ") \n" except AttributeError: ep_str += "Not valid! address = %d" % self.ep_to_kick else: ep_str += "NULL\n" ep_str = ep_str + str(self.cbops) if self.is_state_type_equal_to_name: ep_str = ep_str + \ str(getattr(self, self.name)) return ep_str
def desc_str(self): """ @brief Returns the description string of the transform. @param[in] self Pointer to the current object """ tf_str = "Address: " + cu.hex(self.address) + "\n" tf_str = tf_str + "Source: " + self.source.compact_name() + "\n" tf_str = tf_str + "Sink: " + self.sink.compact_name() + "\n" if self.created_buffer: tf_str = tf_str + "The transform created the buffer \n" else: tf_str = tf_str + "The buffer was supplied by an endpoint \n" if self.shared_buffer: tf_str = tf_str + "The buffer shared \n" else: tf_str = tf_str + "The buffer is not shared \n" tf_str = tf_str + 'Buffer: ' + cu.hex(self.buffer) + '\n' return tf_str
def __str__(self): if self.nearest_label is None: nearest_label_str = "Uncalculated" else: nearest_label_str = str(self.nearest_label) # Using str(x) here since it copes with the value being None return ('Code address: ' + cu.hex(self.address) + '\n' + 'Module name: ' + str(self.module_name) + '\n' + 'Found in: ' + self.src_file + ', line ' + str(self.line_number) + '\n' + 'Nearest label is: ' + nearest_label_str)
def _call_debuginfo_pm_addr(self, address, function_name): """ @brief Searches for the right debuginfo (Kymera or downloadable bundles) and call the function specified at the input. @param[in] self Pointer to the current object @param[in] address Code address. @param[ou] function_name Name of the function to call. """ if Arch.get_pm_region(address, False) is None: raise ct.InvalidPmAddress("Key " + cu.hex(address) + " is not in PM") if self._address_in_table(address): # elf_id_from_address should be different than None elf_id_from_address = self.table.get_elf_id_from_address( address ) if elf_id_from_address not in self.debug_infos: # No bundles are loaded to ACAT at all raise ct.BundleMissingError( BUNDLE_ERROR_MSG.format( cu.hex(elf_id_from_address) ) ) address = self.table.convert_addr_to_download( address, elf_id_from_address ) else: # Use the main Kymera debug info and the patches. elf_id_from_address = None return self._call_debuginfo_elfid( elf_id_from_address, function_name, address )
def analyse_processor_regs(self): """ @brief This just prints out all of the processor registers. Probably only useful in Interactive mode. @param[in] self Pointer to the current object """ # Can't always work out the address of registers to sort them, # so they'll appear in some random dictionary order (sadly). self.formatter.section_start('Processor registers') # Sort by address for name, val in self.chipdata.get_all_proc_regs().iteritems(): self.formatter.output(name + "\t" + cu.hex(val)) self.formatter.section_end()
def convert_addr_to_download(self, addr_in_build, cap_elf_id): ''' @brief Method for converting global address of chipdata to local address of downloaded capability. If conversion is not valid according to the table, None is returned @param[in] addr_in_file - address we want to convert @param[in] cap_elf_id - id of capability we want to map ''' self._update_table() entry = self.get_table_entry(addr_in_build, cap_elf_id, False) if entry is None: raise ValueError("Address " + cu.hex(addr_in_build) + " is not in any downloadable capability.") else: offset = addr_in_build - entry.device_address file_address = entry.file_address + offset return file_address
def analyse_wakeup_timer(self): """ @brief Outputs details of the wakeup timer. @param[in] self Pointer to the current object """ self.formatter.section_start('Wakeup Timer') wakeup_timer_en = self.chipdata.get_reg_strict('$_TIMER2_EN').value wakeup_timer_time = self.chipdata.get_reg_strict( '$_TIMER2_TRIGGER').value if wakeup_timer_en is 1: self.formatter.output('Wakeup time is: ' + cu.hex(wakeup_timer_time)) else: self.formatter.output('No wakeup timer is configured.') self.formatter.section_end()
def get_operator(self, opid): """ @brief Returns the operator (an Operator object) that has ID 'opid'. Returns None if opid was not found. Note: 'operator ID' can be an actual opid (1, 2, etc.) or an operator ep_id (0x4040, 0xe040) - we'll infer which one it is. If force_read == True, the op_list variable is read again (if contents have changed). @param[in] self Pointer to the current object @param[in] opid """ real_opid = Opmgr.get_opid_from_ep_id(opid) self.op_list_object = self.get_oplist('object') for operator in self.op_list_object: if operator.id == real_opid: return operator raise ct.AnalysisError("No operator found with id: " + cu.hex(opid))
def output_list(self, string_to_output): """ @brief Normal body text. Lists/dictionaries will be printed in long-form. @param[in] self Pointer to the current object @param[in] string_to_output """ if isinstance(string_to_output, (list, tuple)): # Less-easy # Printing to the screen is slow, so do it as one big string to go # faster list_string = "" for t in string_to_output: list_string += cu.hex(t) + "\n" # Remove the last '\n' list_string = list_string[:-1] self.output(list_string) else: # Easy self.output(string_to_output)