def get_table(self): if not gdb_stopped() or not inferior_alive(): raise RuntimeError rows_regs = [] for regname in self.regnames: regvalue = valcache(regname) self.regvals[regname] = str(regvalue) chunks = self.get_register_chunks(regname=regname, regvalue=regvalue) col = {'chunks': chunks} row = {'columns': [col]} rows_regs.append(row) return {'rows': rows_regs}
def value(self): ''' Вернуть gdb.Value, которое соответствует path''' path = self.path_from_root() value = gdb.parse_and_eval(path[0]) for name in path[1:]: if type(name) is gdb.Type: value = value.cast(name) else: assert type(name) in (int, str, unicode, gdb.Field), 'path={path}'.format( path=path) try: value = value[name] except gdb.error: return None #gdb_print('cant access path=%s id=%s\n' % (str(self),self.id)) return valcache(value)
def is_array_fetchable(self, arr, n1, n2): '''Данная функция возвращает True, если элементы массива с номерами [n1,n2] включая концы доступны для чтения. False в противном случае. Прочитанные (fetch_lazy) значения массива будут сохранены в кэш. ''' try: valcache(arr[n1]).fetch_lazy() if n2 == None: return True valcache(arr[n2]).fetch_lazy() for i in range(n1 + 1, n2): valcache(arr[i]).fetch_lazy() except gdb.MemoryError: return False return True
def get_local_variables(frame): if not frame: return {} try: block = frame.block() except RuntimeError: return {} variables = {} while block: for symbol in block: if (symbol.is_argument or symbol.is_variable): name = symbol.name if name not in variables: variables[name] = valcache(symbol.value(frame)) if block.function: break block = block.superblock ordered_vars = OrderedDict() for key in sorted(variables): ordered_vars[key] = variables[key] return ordered_vars
def get_frame_func_args(frame): ''' Возвращает список пар: (имя аргумента, строковое представление аргумента) ''' args = [] try: block = frame.block() except RuntimeError: return [] while block: for sym in block: if sym.is_argument: value = valcache(sym.value(frame)) try: strvalue = stringify_value(value) except ValueUnavailable: strvalue = ValueUnavailable.default_stub args.append((sym.name, strvalue)) if block.function: break block = block.superblock if (not block): break return args
def get_local_vars_1(self): try: frame = gdb.selected_frame() except gdb.error: return [] if not frame: return [] try: block = frame.block() except RuntimeError: return [] variables = {} while block: for symbol in block: if (symbol.is_argument or symbol.is_variable): name = symbol.name if name not in variables: variables[name] = valcache(symbol.value(frame)) if block.function: break block = block.superblock return variables
def struct_to_chunks(self, value, name, path, fields=None, expand_depth=0, **kwargs): ''' :param fields: list of gdb.Field If this argument specified then only this fields will be print ''' type_code = value.type.strip_typedefs().code #may be union or struct chunks = [] chunks += self.chunks_type_name(value, name, **kwargs) value_addr = value.address #first check whether we can read memory occupied by struct (value) collapsed = self.expand_variable.get(path.id) expand_single = self.expand_single_array_elem( path ) #True, Если данная структура получается в результате разыменования уазателя, #причем в slice у указателя стоит только один элемент, а не диапазон. ok_expand_depth = expand_depth > 0 if (collapsed == False) or (collapsed == None and not expand_single and not ok_expand_depth): chunks += self.collapsed_struct_to_chunks(path, **kwargs) return chunks chunks1 = [] data_chunks = [] base_classes = [] target_fields = fields if fields else value.type.strip_typedefs( ).fields() try: for idx, field in enumerate(target_fields): field_value, field_name, value_path = None, None, None if field.is_base_class: base_type = gdb.lookup_type(field.name) field_value = value.cast(base_type) tochunks = lambda value, name, path, **kwargs: self.value_to_chunks_1( value=value, name='<INHERITANCE>', path=path, **kwargs) value_path = path.cast(base_type, tochunks=tochunks) else: field_name = field.name if field_name == None: #this is anonymous field. For example: # class A { # union { # int x; # double y; # }; # }; # class A have fielns x,y and UNION is anonimous field value_name = self.type_code_to_string[field.type.code] tochunks = ( lambda value_name: lambda value, name, path, ** kwargs: self.value_to_chunks_1( value=value, name=value_name, path=path, **self.update_kwargs( expand_depth=max(1, expand_depth - 1), print_typename=False, kwargs=kwargs)))(value_name) field_value = value[field] value_path = path.append(name=(idx, None), tochunks=tochunks, field=field) else: field_value = valcache(value[field_name]) value_path = path.append(name=field_name) tochunks = lambda value, name, path, **kwargs: self.value_to_chunks_1( value, name, path, **kwargs) data_chunks += tochunks(field_value, field_name, value_path, expand_depth=expand_depth - 1, **kwargs) data_chunks.append({'str': '\n'}) if type_code == gdb.TYPE_CODE_STRUCT: chunks1.append({ 'chunks': data_chunks, 'type_code': 'TYPE_CODE_STRUCT' }) elif type_code == gdb.TYPE_CODE_UNION: chunks1.append({ 'chunks': data_chunks, 'type_code': 'TYPE_CODE_UNION' }) chunks.append({ 'str': '{\n', 'onclick_data': self.base_onclick_data('collapse_variable', path_id=path.id), }) chunks.append({ 'chunks': chunks1, }) chunks.append({ 'str': '\n}\n', 'onclick_data': self.base_onclick_data('collapse_variable', path_id=path.id), }) except: chunks = [UNAVAILABLE_CHUNK] return chunks
def array_to_chunks(self, value, name, n1, n2, path, slice_clickable=True, **kwargs): ''' Конвертация массива или указателя, который указывает на массив в json-дерево. Args: n1 (int): Начиная с этого номера элементы массива будут напечатаны. n2 (int): включительно по этот номер будут напечатаны элементы массива. Если элементы массива не указатели, то печатается нечто вроде arr = [p1,p2,..,pn] Если элементы массива есть указатели, тип которых не "char *" и не "void *", то печатается конструкция вида arr = [ *(p1) = [...] *(p2) = [...] ] Где p1,p2 есть адреса, а конструкция между [...] есть содержимое указателя ''' chunks = [] type_code = value.type.strip_typedefs().code if name != None: if kwargs.get('print_typename', True): chunks += self.value_type_to_chunks(value, **kwargs) chunks.append({'str': ' '}) if type(name) is str: slice_chunk = self.make_slice_chunk( n1, n2, path, slice_clickable=slice_clickable) varname = [ { 'str': name, 'name': 'varname' }, slice_chunk, ] chunks += varname else: chunks += name chunks += [{'str': ' = '}] #if read address of value is impossible then impossible evaluate value[idx]. if not self.address_available(value): chunks.append(UNAVAILABLE_CHUNK) return chunks if not self.expand_variable.get(path.id): chunks += self.collapsed_array_to_chunks(path, **kwargs) return chunks chunks1 = [] array_data_chunks = [] n22 = n2 + 1 if n2 != None else n1 + 1 deref_value = value[n1] deref_type_code = deref_value.type.strip_typedefs().code deref_type_str = str(deref_value.type.strip_typedefs()) if deref_type_code == ( gdb.TYPE_CODE_PTR and not re.match('.*((char \*)|(void \*))$', deref_type_str) and not is_incomplete_type_ptr(deref_value)): elem_as_array = True else: elem_as_array = False arr_elem_size = deref_value.type.strip_typedefs().sizeof arr_size = n2 - n1 + 1 if n2 != None else 1 if 'delimiter' in kwargs: delimiter = kwargs['delimiter'] else: if deref_type_code in (gdb.TYPE_CODE_INT, gdb.TYPE_CODE_FLT): delimiter = {'str': ', '} else: delimiter = {'str': ',\n'} for i in range(n1, n22): value_idx = valcache(value[i]) if value_idx.is_optimized_out: elem_chunk = OPTIMIZED_OUT_CHUNK else: if elem_as_array: #pointer, not really array tochunks = lambda value, name, path, **kwargs: self.subarray_pointer_data_chunks( value, path, **kwargs) else: if deref_type_code == gdb.TYPE_CODE_ARRAY: tochunks = lambda value, name, path, **kwargs: self.value_to_chunks_1( value=value, name='', path=path, suppress_array_addr=True, **kwargs) else: tochunks = lambda value, name, path, **kwargs: self.value_to_chunks_1( value=value, name=None, path=path, **kwargs) #we can try read memory that occupies element of array, but it is bad approach. #Because in this check we read memory and if OK then when we will convert value to tree #we secondary will be read memory. In embedding systems reading of memory can take a lot of time. # # According to this, we convert value to and if in some place we get error, exception # ValueUnavailable will be raised. tochunks = self.catch_unavailable(tochunks) path_idx = path.append( name=i, tochunks=tochunks, ) chs = tochunks( value_idx, None, path_idx) #inside this function id must be appended assert len(chs) == 1 elem_chunk = chs[0] assert 'id' in elem_chunk array_data_chunks.append(elem_chunk) if delimiter and i != n22 - 1: array_data_chunks.append(delimiter) array_data_chunks.append({'str': '\n'}) chunks1.append({ 'chunks': array_data_chunks, 'type_code': 'TYPE_CODE_ARRAY' }) chunks.append({ 'str': '[\n', 'onclick_data': self.base_onclick_data('collapse_variable', path_id=path.id) }) chunks.append({ 'chunks': chunks1, 'name': 'parenthesis', }) chunks.append({ 'str': '\n]\n', 'onclick_data': self.base_onclick_data('collapse_variable', path_id=path.id) }) return chunks